默认构造函数和析构函数的“ = default”与“ {}”有何不同?

我最初将其发布为仅关于析构函数的问题,但现在我添加了对默认构造函数的考虑。这是原始问题:


如果我想给我的类一个虚拟的析构函数,但在其他方面与编译器生成的析构函数相同,则可以使用=default:


class Widget {

public:

   virtual ~Widget() = default;

};

但是似乎我可以通过使用空定义进行更少的键入而获得相同的效果:


class Widget {

public:

   virtual ~Widget() {}

};

这两种定义有什么不同的表现方式吗?


根据针对此问题发布的答复,默认构造函数的情况似乎类似。既然对于析构函数,“ =default”和“ {}”之间的含义几乎没有差异,那么对于默认构造函数,这些选项之间的含义几乎也没有差异吗?也就是说,假设我要创建一个将同时创建和销毁该类型的对象的类型,为什么我要说


Widget() = default;

代替


Widget() {}


如果在发布原始问题后扩展此问题违反了某些SO规则,我深感抱歉。为默认构造函数发布一个几乎相同的问题令我震惊,因为它是不太理想的选择。


慕运维8079593
浏览 5177回答 3
3回答

繁星coding

当询问构造函数时,这是一个与析构函数完全不同的问题。如霍华德指出virtual,如果您的析构函数是,则差异可以忽略不计。但是,如果您的析构函数不是虚拟的,那就完全不一样了。构造函数也是如此。= default对特殊的成员函数(默认构造函数,复制/移动构造函数/赋值,析构函数等)使用语法意味着与简单地做有很大的不同{}。使用后者,该功能将变为“用户提供”。这改变了一切。根据C ++ 11的定义,这是一个琐碎的类:struct Trivial{  int foo;};如果尝试默认构造一个,则编译器将自动生成一个默认构造函数。复制/移动和销毁也是如此。因为用户没有提供任何这些成员函数,所以C ++ 11规范将其视为“琐碎的”类。因此,这样做是合法的,例如将其内容memcpy初始化以此类推。这个:struct NotTrivial{  int foo;  NotTrivial() {}};顾名思义,这不再是琐碎的事。它具有用户提供的默认构造函数。它是否为空无关紧要;就C ++ 11的规则而言,这不能是琐碎的类型。这个:struct Trivial2{  int foo;  Trivial2() = default;};顾名思义,这是一个琐碎的类型。为什么?因为您告诉编译器自动生成默认构造函数。因此,构造函数不是“用户提供的”。因此,该类型被认为是微不足道的,因为它没有用户提供的默认构造函数。= default当添加阻止创建此类函数的成员函数时,该语法主要用于执行诸如复制构造函数/赋值之类的操作。但是它还会触发编译器的特殊行为,因此它在默认构造函数/析构函数中也很有用。

红糖糍粑

他们都是不平凡的。它们都具有相同的noexcept规范,具体取决于基础和成员的noexcept规范。到目前为止,我检测到的唯一区别是,如果Widget包含具有不可访问或删除的析构函数的基或成员:struct A{private:    ~A();};class Widget {    A a_;public:#if 1   virtual ~Widget() = default;#else   virtual ~Widget() {}#endif};然后,=default解决方案将编译,但Widget不会是可破坏的类型。即,如果您尝试破坏Widget,则会收到编译时错误。但是,如果不这样做,您就有一个有效的程序。Otoh,如果您提供用户提供的析构函数,则无论您是否解构a,事情都不会编译Widget:test.cpp:8:7: error: field of type 'A' has private destructor    A a_;      ^test.cpp:4:5: note: declared private here    ~A();    ^1 error generated.
打开App,查看更多内容
随时随地看视频慕课网APP