如何强制调用移动构造函数,我为什么要这样做?
How to force the call to move constructor and why should I do that?
我测试了这段代码,发现编译器无需移动构造函数即可自动将临时对象传输到变量。
#include <iostream>
using namespace std;
class A
{
public:
A()
{
cout<<"Hi from default\n";
}
A(A && obj)
{
cout<<"Hi from move\n";
}
};
A getA()
{
A obj;
cout<<"from getA\n";
return obj;
}
int main()
{
A b(getA());
return 0;
}
此代码打印 "Hi from default from getA" 而不是假定的 "Hi from move"
在优化方面,它很棒。但是,如何在不添加副本的情况下强制调用移动构造函数? (如果我想要临时对象的特定行为)
补充问题:我认为如果我不编写移动构造函数,那么每次我将右值分配给左值时都会有一个副本(就像在 A b(getA());
行的代码中一样)。既然不是这样,而且编译器似乎做得很好,那么什么时候实现移动语义才真正有用?
In optimisation terms, it's great. But, how to force the call to the move constructor without adding a copy ? (if I wanted a specific behavior for my temporary objects)
通常这需要禁用优化标志才能获得此行为。对于 gcc 和 clang,您可以使用 -fno-elide-constructors
关闭复制 elison。对于 MSVS,它不会在调试模式下执行此操作(优化已关闭),但我不确定他们是否有针对此的特定标志
您还可以在 return 语句中调用 std::move
,这将禁用省略并强制编译器生成临时文件并从中移动。
return std::move(obj);
也就是说,RVO/NRVO 是您应该想要的东西。如果可以的话,您甚至不希望创建临时文件,因为完成的工作更少意味着您可以同时完成更多的工作。为此,C++17 引入了 ,它阻止了那些临时对象的存在。
这并不意味着您不应该尽可能地编写一个移动构造函数(如果您遵循 rule of zero 那么您就不会编写一个而只使用编译器提供的一个)。有时编译器无法省略一个临时值,或者您想移动一个左值,所以它仍然是一个有用的东西。
我测试了这段代码,发现编译器无需移动构造函数即可自动将临时对象传输到变量。
#include <iostream>
using namespace std;
class A
{
public:
A()
{
cout<<"Hi from default\n";
}
A(A && obj)
{
cout<<"Hi from move\n";
}
};
A getA()
{
A obj;
cout<<"from getA\n";
return obj;
}
int main()
{
A b(getA());
return 0;
}
此代码打印 "Hi from default from getA" 而不是假定的 "Hi from move"
在优化方面,它很棒。但是,如何在不添加副本的情况下强制调用移动构造函数? (如果我想要临时对象的特定行为)
补充问题:我认为如果我不编写移动构造函数,那么每次我将右值分配给左值时都会有一个副本(就像在 A b(getA());
行的代码中一样)。既然不是这样,而且编译器似乎做得很好,那么什么时候实现移动语义才真正有用?
In optimisation terms, it's great. But, how to force the call to the move constructor without adding a copy ? (if I wanted a specific behavior for my temporary objects)
通常这需要禁用优化标志才能获得此行为。对于 gcc 和 clang,您可以使用 -fno-elide-constructors
关闭复制 elison。对于 MSVS,它不会在调试模式下执行此操作(优化已关闭),但我不确定他们是否有针对此的特定标志
您还可以在 return 语句中调用 std::move
,这将禁用省略并强制编译器生成临时文件并从中移动。
return std::move(obj);
也就是说,RVO/NRVO 是您应该想要的东西。如果可以的话,您甚至不希望创建临时文件,因为完成的工作更少意味着您可以同时完成更多的工作。为此,C++17 引入了
这并不意味着您不应该尽可能地编写一个移动构造函数(如果您遵循 rule of zero 那么您就不会编写一个而只使用编译器提供的一个)。有时编译器无法省略一个临时值,或者您想移动一个左值,所以它仍然是一个有用的东西。