【问题标题】:When will the move ctor be invoked?何时调用移动 ctor?
【发布时间】:2026-01-03 20:30:02
【问题描述】:

给定类:

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;)在什么情况下会被调用?

【问题讨论】:

    标签: c++ constructor c++11


    【解决方案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
            

            【讨论】:

            • 投反对票时请留言
            最近更新 更多