8

我有一个包含 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;
};

上述实现是否正确?

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

在此先感谢您的任何建议。(我知道已经有一些类似的问题,但不适用于这种确切的情况。)

4

2 回答 2

6

对于此类[*],它们都是不必要的,因为如果您没有声明它们中的任何一个,它将具有隐含的。

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

A f() { return A(); }
A a = f(); // move construct (not copy construct) from the return value of f

事实上,移动省略可能会起作用,在这种情况下,实际上只调用了无参数构造函数。我假设您计划提供一些构造函数,而不是复制和移动;-)

您的复制分配很好,它与隐式分配的不同之处仅在于它具有自分配检查,而隐式分配则没有。我认为我们不应该争论自分配检查是否值得,这不是不正确的。

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

A a;
a = f();

[*] 在一个完整的 C++11 实现上,目前还没有。您可以在每个编译器的基础上检查此功能是否已实现,并且#define在 MSVC 实现之前,您可能会遇到一些可怕的恶作剧。

于 2013-01-08T11:22:18.903 回答
2

对于这个确切的场景,您不需要声明任何移动/复制/分配函数。编译器将生成正确的默认值。

于 2013-01-08T10:16:18.150 回答