如何强制调用移动构造函数,我为什么要这样做?

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 那么您就不会编写一个而只使用编译器提供的一个)。有时编译器无法省略一个临时值,或者您想移动一个左值,所以它仍然是一个有用的东西。