显式默认的析构函数禁用类中的默认move构造函数 [英] Explicitly defaulted destructor disables default move constructor in a class

查看:74
本文介绍了显式默认的析构函数禁用类中的默认move构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have run into a problem that a move constructor of a superclass did not get invoked properly when its subclass has an explicitly defaulted destructor. The move constructor does get invoked when the destructor is implicitly defaulted (not provided at all in the supclass definition).

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

I am aware of the constraints that the compilers should apply to default move constructors. Yet, I have been by all means sure that the compiler should not discriminate between explicitly/implicitly defaulted destructors (or constructors as well) when applying these rules. In other words, explicitly defaulted destructor should not be treated as user-defined one (in contrast to an empty user-defined destructor ).

仅通过MSVC 2019测试.

Tested with MSVC 2019 only.

我还是MSVC在这里?

Am I or MSVC right here?


#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));

}


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

EXPECTED: Display "I am moving :)" in all cases

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

ACTUAL : Displays "Auch, they'r making copy of me(?!)" in case D

推荐答案

D 中声明默认的析构函数时,将禁用编译器生成的move构造函数,并在 D中移动赋值运算符(!),不是基类版本.这就是为什么使用 E 获得预期输出的原因,在该代码中,通过显式 = default 特殊成员函数来覆盖编译器的默认操作.编译器生成的move构造函数对可移动基类类型做了正确的处理,因此请遵循五个规则 = default 特殊成员函数表示 D .

When you declare a defaulted destructor in D, you disable the compiler-generated move constructor and move assignment operator in D (!), not the base class version. This is why you get the expected output with E, where you override the defaulted operation by the compiler by explicitly = defaulting the special member functions. The compiler-generated move constructor does the right thing for movable base class types, so follow the rule of five and = default the special member functions for D.

请查看此答案中的表格.这是保存在枕头下的非常有用的参考.

Have a look at the table in this answer. It's a very useful reference to be kept under the pillow.

这篇关于显式默认的析构函数禁用类中的默认move构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆