1

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

  1. 仅针对缺少
    显式声明的移动操作、复制操作或析构函数的类生成移动操作。

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

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

// 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;
}

第一个断言可能因环境而异,但第二个断言几乎是错误的。
我对此感到非常困惑。请帮帮我。

4

1 回答 1

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 确实尝试使用复制构造函数,但它不能。

于 2017-04-15T16:47:36.923 回答