何时调用移动 ctor?

Posted

技术标签:

【中文标题】何时调用移动 ctor?【英文标题】:When will the move ctor be invoked? 【发布时间】:2010-08-05 09:18:21 【问题描述】:

给定类:

class C

public:
    C()
    
        cout << "Dflt ctor.";
    
    C(C& obj)
    
        cout << "Copy ctor.";
    
    C(C&& obj)
    
        cout << "Move ctor.";
    
    C& operator=(C& obj)
    
        cout << "operator=";
        return obj;
    
    C& operator=(C&& obj)
    
        cout << "Move operator=";
        return obj;
    
;

然后在 main:

int main(int argc, char* argv[])

    C c;
    C d = c;
    C e;
    e = c;
    return 0;

正如您将从输出中看到的那样,调用了“常规”版本的复制 ctor 和 operator=,但没有调用具有右值参数的那些。所以想问一下move ctor和operator=(C&amp;&amp;)在什么情况下会被调用?

【问题讨论】:

【参考方案1】:

当右侧是临时的,或者使用static_cast&lt;C&amp;&amp;&gt;std::move 显式转换为C&amp;&amp; 时,将调用移动构造函数。

C c;
C d(std::move(c)); // move constructor
C e(static_cast<C&&>(c)); // move constructor
C f;
f=std::move(c); // move assignment
f=static_cast<C&&>(c); // move assignment
C g((C())); // move construct from temporary (extra parens needed for parsing)
f=C(); // move assign from temporary

【讨论】:

【参考方案2】:

IIRC,你必须使用C d = std::move(c) 才能使用移动构造函数。

一个未经测试的例子,但可以更好地解释移动构造函数的使用:

C&& foo()  C c; return std::move(c); 

【讨论】:

【参考方案3】:

您的所有变量都是左值,因此不能隐式移动,因为您以后可能需要访问它们。此外,复制构造函数和赋值运算符采用 const 引用。

右值引用适用于右值,即临时对象。为了查看使用的移动构造函数,首先,您必须实际创建一个临时对象。此外,不要忘记 RVO 仍然适用,并且很可能会确定您的任何或所有 std::cout 调用。

您可以使用 std::move(lvalue) 从左值创建右值。

【讨论】:

【参考方案4】:
std::swap(c,e); // c and e variables declared in your _tmain()

将调用移动构造函数。

【讨论】:

【参考方案5】:

如果你有一个静态类,它返回在本地堆栈上创建的 C&&,则更实际的使用移动运算符的示例如下:

static C&& CreateC()

   C c();
   //do something with your object
   return c;

然后你像这样调用它:

C x = CreateC(); // move operator is invoked here

【讨论】:

投反对票时请留言

以上是关于何时调用移动 ctor?的主要内容,如果未能解决你的问题,请参考以下文章

自动生成默认/复制/移动 ctor 和复制/移动赋值运算符的条件?

将 std::string ctor 参数传递给具有移动语义的 pimpl 中的 impl

std::any 用于仅移动模板,其中 copy-ctor 内的 static_assert 等于编译错误,但为啥呢?

ktor 服务器 - 何时移动到另一个协程上下文

检测窗口何时停止移动?

编译器何时不生成移动构造函数和移动赋值?