为什么当定义析构函数时,编译器不再添加默认的move函数和赋值函数

Why default move ctor and assignment are no more added by compiler when a destructor is defined?

本文关键字:函数 默认 move 添加 赋值 不再 定义 析构函数 编译器 为什么      更新时间:2023-10-16

我无法理解自动添加默认角色背后的原理。尤其让我感到尴尬的是,每次我只需要添加一个空的虚析构函数,仅此而已,我就丢失了move之类的东西,但添加它们时,我又丢失了copy和default之类的东西,所以我最后添加了所有这些代码块:

virtual ~SomeClass(){}           // you are the guilty!
//virtual ~SomeClass() = default // would be the same
SomeClass(SomeClass&&) = default;                 // no more auto-added
SomeClass& operator=(SomeClass&&) = default;      // no more auto-added
SomeClass(const SomeClass&) = default;            // but with the moves defined,
SomeClass& operator=(const SomeClass&) = default; // I'm now missing the copy
SomeClass(){}                                     // and the default as well

我确信有一个原因使我的类丑陋,让我想要一个邪恶的宏,我只是想知道它感觉更舒服。

看看这个。它解释了所谓的"五法则",这基本上是标准所要求的。

通常,在大多数情况下,编译器会为复制构造函数、复制赋值、move赋值和析构函数创建默认值。但是,如果程序员定义了其中的任何一个,那么编译器就会假设用户在这个类中封装了一些需要他/她的特殊功能的东西。析构函数。既然程序员知道他/她将需要一个析构函数,编译器将知道程序员知道发生了什么,而不会为其余部分创建默认值(因为,基于编译器所做的假设,默认值将是错误的,甚至可能导致不希望的行为)。

问题是您的类试图做两件独立的事情:提供多态接口(因此需要虚拟析构函数)和管理具体的数据成员(因此需要复制/移动操作)。一般来说,给每个类一个单独的职责是个好主意。

我将把虚析构函数和虚函数声明移到一个空的抽象基类中。然后,从它派生的任何具体类都可以自由地自动生成所有需要的东西。

的例子:

#include <iostream>
struct Movable {
    Movable() {}
    Movable(Movable&&m) {std::cout << "Movingn";}
};
struct SomeInterface {
    virtual ~SomeInterface() {}
    // no data members, so no need for any other special member functions
};
struct SomeClass : SomeInterface {
    Movable stuff;
    // no user-declared special functions, so all are auto-generated
};
int main() {
    SomeClass c;
    SomeClass c2(std::move(c));  // uses the auto-generated move constructor
}