【问题标题】:How to ensure the move constructor is used如何确保使用移动构造函数
【发布时间】:2016-05-23 09:08:48
【问题描述】:

下面的代码给出了错误:

use of deleted function ‘constexpr B::B(const B&)’

现在,我知道会发生这种情况,因为通过指定移动构造函数(有意)隐式删除了复制构造函数,并且复制向量会导致调用(已删除)复制构造函数。我想我也明白为什么要使用向量的复制构造函数和赋值运算符了。我显然想使用移动构造函数和赋值运算符:移动对象,所以也要移动它包含的向量。那么,如何让我的移动构造函数/赋值运算符使用向量的移动构造函数/赋值运算符?

代码如下:

#include <vector>

class B {
private:
    /* something I don't want to copy */
public:
    B() {};
    B(B&& orig) {/* move contents */};
    B& operator=(B&& rhs) {
        /* move contents */
        return *this;
    };
};

class A {
private:
    vector<B> vec;
public:
    A() : vec() {};
    A(A&& orig) : vec(orig.vec) {};
    A& operator=(A&& rhs) {
        vec = rhs.vec;
        return *this;
    };
};

【问题讨论】:

    标签: c++ c++11 move-constructor move-assignment-operator


    【解决方案1】:

    只需在要从其中移动的表达式中的向量上调用 std::move

    class A {
    private:
        vector<B> vec;
    public:
        A() : vec() {};
        A(A&& orig) : vec(std::move(orig.vec)) {};
        //                ^^^^^^^^^
        A& operator=(A&& rhs) {
            vec = std::move(rhs.vec);
            //    ^^^^^^^^^
            return *this;
        };
    };
    

    即使你接受了右值引用,rhsorig 在函数中仍然是左值,所以你需要对它们调用std::move

    【讨论】:

      【解决方案2】:

      为确保调用“移动”构造函数和赋值运算符,您需要提供正确值类别的对象。值类别用于确定可以使用哪些运算符和构造函数。

      使用std::movevalue category(在本例中为左值)更改为x 值(右值,可以从中移动)。

      // ...
      A(A&& orig) : vec(std::move(orig.vec)) {};
      A& operator=(A&& rhs) {
          vec = std::move(rhs.vec);
          return *this;
      };
      

      move 不会以任何方式复制或更改对象,它只是转换为参数类型的右值引用 - 因此修改了值类别。

      【讨论】:

        【解决方案3】:

        如果您的类的所有成员都是具有正确定义的移动构造函数/赋值运算符的类的对象,那么您最好为您的类使用default 移动构造函数/赋值运算符。这将更容易且不易出错,并确保调用类成员的移动构造函数/赋值运算符。

        在您的特定示例中,它将是:

        class A
        {
        private:
            vector<B> vec;
        public:
            A() : vec() {};
            A(A&&) = default;
            A& operator=(A&&) = default;
        };
        

        【讨论】:

        • 我发现在规范中很难找到,但我假设默认移动构造函数调用所有基类和成员的移动构造函数?如果是这样,这可能是这种情况下的正确解决方案。
        • @Oebele 观看draft C++11 standard 的第 12.8 节第 15 段
        猜你喜欢
        • 2016-03-28
        • 2012-10-10
        • 2011-05-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多