显式默认的析构函数禁用类中的默认move构造函数

时间:2019-07-10 10:10:33

标签: c++ c++11 default destructor move-semantics

我遇到了一个问题,当超类的子类具有显式默认的析构函数时,超类的move构造函数无法正确调用。隐式默认使用析构函数时,将调用move构造函数(在supclass定义中完全未提供)。

我知道constraints,编译器应将其应用于默认的move构造函数。但是,我已经完全确定,在应用这些规则时,编译器不应区分显式/隐式默认析构函数(或构造函数)。换句话说,显式默认的析构函数不应视为用户定义的析构函数(与empty用户定义的析构函数相反)。

仅通过MSVC 2019测试。

我还是MSVC在这里?


#include <iostream>

class A {
public:
    A() = default;
    A(const A&) { std::cout << "Auch, they'r making copy of me(?!)" << std::endl; }
    A(A&&) { std::cout << "I am moving :)" << std::endl; }

    ~A() = default;
};

class B : public A {
public:

};

class C : public A {
public:

    C() = default;

};

class D : public A {
public:

    ~D() = default;

};

class E : public A {
public:

    E() = default;
    E(const E&) = default;
    E(E&&) = default;
    ~E() = default;

};

int main()
{

    std::cout << "\n---- A ----\n" << std::endl;

    A a;
    A a2(std::move(a));

    std::cout << "\n---- B ----\n" << std::endl;

    B b;
    B b2(std::move(b));

    std::cout << "\n---- C ----\n" << std::endl;

    C c;
    C c2(std::move(c));

    std::cout << "\n---- D ----\n" << std::endl;

    D d;
    D d2(std::move(d));

    std::cout << "\n---- E ----\n" << std::endl;

    E e;
    E e2(std::move(e));

}


已执行:在所有情况下均显示“我正在移动:)”

ACTUAL:如果出现D,则显示“好了,他们正在复制我(?!)”

1 个答案:

答案 0 :(得分:1)

D中声明默认的析构函数时,将在D(!)中禁用编译器生成的move构造函数并移动赋值运算符,( not 基类版本。这就是为什么通过E获得期望的输出的原因,其中您通过显式= default显式使用特殊成员函数来覆盖编译器的默认操作。编译器生成的move构造函数对可移动基类类型做了正确的处理,因此请遵循= default的{​​{3}}和D特殊成员函数。

看看rule of five中的表。将它放在枕头下是非常有用的参考。