“Effective Modern C ++”中的C ++默认移动操作

时间:2017-04-15 16:33:45

标签: c++11 move-semantics effective-c++

第17项:了解特殊成员函数的生成。

  1. 仅针对缺少的分类生成移动操作 明确声明移动操作,复制操作, 或者是一个析构函数。

  2. 现在,当我提到移动操作移动构造时 或移动 - 分配数据成员或基类,有 并不保证会实际采取行动 实际上,“成员行动”更像是成员 移动请求,因为未启用移动的类型(...)
    将通过他们的复制操作“移动”。

  3. 但是,我无法在我的环境中验证它们。

    // compiled
    #include <iostream>
    using namespace std;
    class Base {
    public:
        ~Base() {}
    };
    int main() {
        Base a, c;
        Base b(move(a));
        c = move(b);
        // explicitly destructor does not disable 
        // default move constuctor and move assignment operator
        return 0;
    }
    
    class Base {
    public:
        Base() {}
        Base(Base& b) {}
        ~Base() {}
    };
    class Num {
    private:
        Base b;
    };
    int main() {
        Num a, c;
        c = move(a); // passed
        Num b(move(c)); // error
        // explicitly Base::Base(Base& b) disable default move 
        // move conctructor. 
        // Num's default move constructor can not find any move
        // constructor for member object Base b, which lead to an 
        // error. Num's default move constructor does not "moved" 
        // Base b via their copy operations which is declared.
        return 0;
    }
    

    第一个断言可能因不同环境而异,但第二个断言几乎是错误的 我很困惑。 请帮帮我。

1 个答案:

答案 0 :(得分:0)

class Base {
public:
    ~Base() {}
};

因为Base具有用户声明的析构函数,所以它根本没有移动构造函数或移动赋值运算符。行

Base b(move(a));
c = move(b);

实际上分别调用了复制构造函数和复制赋值运算符。

class Base {
public:
    Base() {}
    Base(Base& b) {}
    ~Base() {}
};
class Num {
private:
    Base b;
};

同样,Base根本没有移动构造函数。但是,Num确实有一个隐式声明的移动构造函数,因为Num本身并不声明任何特殊的成员函数。但是,它被隐式定义为已删除,因为默认定义将是格式错误的:

Num::Num(Num&& n) : b(std::move(n.b)) {}
// Cannot convert rvalue of type `Base` to `Base&`
// for the copy constructor to be called.

请注意,b 的“移动”会尝试使用复制构造函数,但它不能。