“= default”析构函数和空析构函数有啥区别?
Posted
技术标签:
【中文标题】“= default”析构函数和空析构函数有啥区别?【英文标题】:What's the difference between "= default" destructor and empty destructor?“= default”析构函数和空析构函数有什么区别? 【发布时间】:2015-03-01 23:15:35 【问题描述】:我想阻止我的类的用户将它用作自动变量,所以我编写了这样的代码:
class A
private:
~A() = default;
;
int main()
A a;
我希望代码不会被编译,但是g++编译它没有错误。
但是,当我将代码更改为:
class A
private:
~A()
;
int main()
A a;
现在,g++ 给出了~A()
是私有的错误,正如我所期望的那样。
“= default”析构函数和空析构函数有什么区别?
【问题讨论】:
什么版本的 gcc? 阅读例如this destructor reference,区别在于用户提供的析构函数(即使它是空的)是非平凡的,并且来自参考:“具有平凡析构函数的对象不需要删除表达式和可以通过简单地释放它们的存储来处理。" 在你的情况下没有区别,gcc4.9 and clang3.5 refuse to compile 你的第一个例子。这一定是您的 gcc 版本中的错误。 我的gcc版本是4.8.2 我认为相关的错误报告是54812 【参考方案1】:您的第一个示例不应编译。这表示它确实编译的编译器中的一个错误。此错误已在 gcc 4.9 及更高版本中修复。
在这种情况下,用= default
定义的析构函数微不足道。这可以通过std::is_trivially_destructible<A>::value
检测到。
更新
C++11(和 C++14)声明如果有一个 user-declared 析构函数(并且如果你没有任何一个用户声明的 move 特殊成员),那么复制构造函数和复制赋值运算符的隐式生成仍然发生,但该行为已被弃用。这意味着如果您依赖它,您的编译器可能会给您一个弃用警告(或可能不会)。
两者:
~A() = default;
和:
~A() ;
是用户声明的,因此它们在这一点上没有区别。如果您使用其中任何一种形式(并且不声明移动成员),则应显式默认、显式删除或显式提供您的副本成员,以避免依赖已弃用的行为。
如果您确实声明了移动成员(声明或不声明析构函数),则复制成员将被隐式删除。
【讨论】:
@delphifirst:现在编译器错误非常普遍。当我还是学生时,在 1980 年代初期,我们了解到任何不良行为肯定是我们代码中的错误,而不是编译器中的错误。今天我经常让编译器崩溃(ICE,Internal Compiler Error),然后毫无疑问是谁的错...... @HowardHinnant:我想念一些关于默认与未声明的讨论。我认为这与标准对“用户声明”一词的使用有关,例如在 C++11 §12.8/18 中。请问? @Cheersandhth.-Alf:很高兴为您提供帮助,但我不明白您的问题。如果您询问=defaulted
特殊成员是否是用户声明的,答案是肯定的,但不是用户提供的。
@HowardHinnant:从字面上看,OP 的问题是““= default”析构函数和空析构函数有什么区别?正如我提到的段落中,关于代码未来含义的差异与恕我直言非常相关。这当然是不同的。
@Cheersandhth.-Alf:您指的是编译器隐式提供复制成员,以及在某些情况下如何弃用?以上是关于“= default”析构函数和空析构函数有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章
C++11 - CTOR() = default 和空 CTOR() 有啥区别? [复制]