移动构造函数(和其他)的正确实现是什么?

Mar*_*cze 7 c++ move-semantics c++11

我有一个包含std :: vector的简单类,我希望在按值返回类时从移动语义(而不是RVO)中受益.

我通过以下方式实现了移动构造函数,复制构造函数和复制赋值运算符:

class A
{
    public:
        // MOVE-constructor.
        A(A&& other) :
            data(std::move(other.data))
        {
        }

        // COPY-constructor.
        A(const A& other) :
            data(other.data)
        {
        }

        // COPY-ASSIGNMENT operator.
        A& operator= (const A& other);
        {
            if(this != &other)
            {
                data = other.data;
            }

            return *this;
        }

    private:
        std::vector<int> data;
};
Run Code Online (Sandbox Code Playgroud)

上述实现是否正确?

还有一个问题:我是否必须实现这些成员中的任何一个,还是由编译器自动生成?我知道默认情况下会生成复制构造函数和复制赋值运算符,但编译器是否也可以自动生成移动构造函数?(我用MSVC和GCC编译这段代码.)

在此先感谢您的任何建议.(我知道已经存在一些类似的问题,但不是针对这种情况.)

Ste*_*sop 6

对于这个类[*]来说,它们都是不必要的,因为如果你没有声明其中的任何一个,它就会有隐式的.

你的建设者很好.所以下面的代码表面上调用了移动构造函数:

A f() { return A(); }
A a = f(); // move construct (not copy construct) from the return value of f
Run Code Online (Sandbox Code Playgroud)

事实上,move-elision可能会启动,在这种情况下,实际上只调用no-args构造函数.我假设您计划提供除复制和移动之外的一些构造函数;-)

您的副本分配是正常的,它与隐式分配的不同之处仅在于它具有自我分配检查,而隐式分配则不会.我不认为我们应该讨论自我分配检查是否值得,这不是不正确的.

您尚未定义移动赋值运算符.鉴于你定义了其他人,你应该已经完成​​了,但是如果你摆脱其余部分,它就是隐含的[*].移动赋值运算符(无论是用户定义的还是隐式的)确保以下代码移动而不是复制:

A a;
a = f();
Run Code Online (Sandbox Code Playgroud)

[*]在已完成的C++ 11实现上,到目前为止还没有.您可以根据每个编译器检查此功能是否已实现,并且可能最终会遇到一些可怕的#define恶作剧,直到MSVC为止.