函数返回类型的std :: move() - 性能c ++ [英] std::move() on function return type - performance c++

查看:195
本文介绍了函数返回类型的std :: move() - 性能c ++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

// visual studio  2013,c ++,发布 

//visual studio  2013, c++ , release 

我以两种不同的方式分配了myfunction()的结果。一个用std :: move,一个没有std :: move()。哪一个在性能方面更好?

I am assigning the result of myfunction() in two different ways. one with std::move and one without std::move(). Which one is better in terms of performance?

std :: string myfunction()

{

std :: string temp;



temp =" bla" + QUOT;," +  " BLA" ; //非常大的字符串 

返回温度;

}



void main()

{



std :: string retval1 = myfunction();

std :: string retval2 = std :: move( myfunction()):
$


}

std::string myfunction()
{
std::string temp;

temp = "bla" +","+  "bla" ; // very large string 
return temp;
}

void main()
{

std::string retval1 = myfunction();
std::string retval2 = std::move(myfunction()):

}

推荐答案

两者都是如此因为我确信编译器不会受到std :: move的影响所以很好。

Both are just as good as each other because I'm sure the compiler would not be affected by the std::move at all.

你看,对于retval1的情况,编译器会使用这个移动反正的构造函数。添加移动对于retval2的情况没有实际效果。换句话说,你不需要做任何特殊的事情来启用移动语义。

You see, for the case of retval1, the compiler would use the move constructor if available anyway. There is no real effect for adding the move like you did in the case for retval2. In other words, you don't need to do anything special to enable move semantics.

当你想保持基类的移动语义时,使用什么std :: move。例如,您对输出的期望是什么:

What std::move is used for is when you want to keep move semantics for a base class. For example, what would you expect for the output of:

#include <iostream>

class baseclass
{
public:
	baseclass()
	{
		std::cout << "base constructor" << "\n";
	}
	baseclass(const baseclass &)
	{
		std::cout << "base copy constructor" << "\n";
	}
	baseclass(baseclass &&)
	{
		std::cout << "base move constructor" << "\n";
	}
	~baseclass()
	{
		std::cout << "base destructor" << "\n";
	}
};

class derivedclass : public baseclass
{
public:
	derivedclass()
	{
		std::cout << "derived constructor" << "\n";
	}
	derivedclass(const derivedclass &d) : baseclass(d)
	{
		std::cout << "derived copy constructor" << "\n";
	}
	derivedclass(derivedclass &&d) : baseclass(d)
	{
		std::cout << "derived move constructor" << "\n";
	}
	~derivedclass()
	{
		std::cout << "derived destructor" << "\n";
	}
};

derivedclass fun()
{
	derivedclass d{};
	return d;
}

int main()
{
	derivedclass d = fun();

	return 0;
}

乍一看,你可能认为它会是这样的:

At first glance you may think that it would be something like:

基础构造函数

派生构造函数

基本移动构造函数

派生移动构造函数

派生析构函数

base析构函数
派生析构函数

基础析构函数

base constructor
derived constructor
base move constructor
derived move constructor
derived destructor
base destructor
derived destructor
base destructor

但令人惊讶,事实并非如此。它实际上是:

But surprise, it isn't. It is actually:

基础构造函数

派生构造函数

基本复制构造函数<<注意这里的拷贝构造函数

派生的移动构造函数<<但这显然是移动构造函数

派生析构函数

基础析构函数

派生析构函数

基础析构函数

base constructor
derived constructor
base copy constructor << notice the copy constructor here
derived move constructor << but this clearly was the move constructor
derived destructor
base destructor
derived destructor
base destructor

那么为什么要调用基类的复制构造函数而不是移动构造函数呢?这是因为移动构造函数为r值引用赋予了名称。因为现在可以访问对象的内容,所以将
视为r值引用通常是不安全的,因此它会静默地将其转换为l值引用。这是std :: move的用武之地。要使基类调用移动构造函数,只需将派生类的移动构造函数更改为:

So why did the copy constructor of the base class get called instead of the move constructor? It is because the move constructor gives the r-value reference a name. Because it is now possible to access the guts of the object it is generally unsafe to treat it like an r-value reference and so it silently converts it to an l-value reference. This is where std::move comes in. To get the base class to call the move constructor, you simply change the move constructor of the derived class to:

derivedclass(derivedclass &&d) : baseclass(std::move(d)) //notice the std::move here
	{
		std::cout << "derived move constructor" << "\n";
	}

这就是全部。输出现在将显示它调用基类的移动构造函数。

That is all. The output will now show that it calls the move constructor of the base class.

所有std :: move都将其转换为r值引用,因此它基本上实现为:

All std::move does is convert it to an r-value reference, so it is essentially implemented like:

template<typename T>
remove_reference<T>&& move(T && arg)
{
    return static_cast<remove_reference<T>&&>(arg);
}

所以是的,它实际上是静态转换为r值引用。它实际上仅用于在r值引用上重新启用移动语义。这只有在您知道正在调用的函数将正确处理移动语义时才有用,
因此您通常只在移动构造函数中看到它。

So yes, it literally static casts to the r-value reference. It is literally only used to re-enable the move semantics on an r-value reference. This is also only useful if you know that the function that you are calling will properly handle the move semantics, so you mostly only see it in move constructors.

所以我的答案如果没有std :: move会对性能更好,因为编译器必须做更少的工作,因为它不需要解析额外的代码。

So my answer would be without std::move would be better for performance since the compiler would have to do less work since it doesn't have to parse the extra code.


这篇关于函数返回类型的std :: move() - 性能c ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆