为何默认/删除构造函数场景下析构函数未调用?关于()的疑问
为什么
Bar b();和Foo f();不会调用析构函数? 这绝对是C里最容易踩坑的语法陷阱之一——咱们俗称的「最令人困惑的语法解析(Most Vexing Parse)」,我当初刚学C的时候也栽过好几次!
核心原因:它们不是对象定义,是函数声明!
当你写下Bar b();或者Foo f();时,编译器不会把它们解析为创建无参对象的代码,而是会优先按照函数声明来处理:
Bar b();等价于:声明一个名为b的函数,该函数没有参数,返回值是Bar类型Foo f();等价于:声明一个名为f的函数,该函数没有参数,返回值是Foo类型
既然根本没有创建任何对象,自然不会调用构造函数初始化对象,程序结束时也没有需要销毁的对象,所以析构函数完全不会被触发。
对比其他写法的差异
- (C)
Foo f;:这是标准的对象定义语法,编译器明确知道你要创建一个Foo类型的对象f,会调用默认构造函数初始化它。当程序生命周期结束(比如main函数返回)时,对象被销毁,析构函数也就被调用了。 - (D)
Bar b;:你尝试直接定义Bar对象,但Bar的默认构造函数被=delete禁用了,编译器会直接报错,提示你无法使用已删除的构造函数。
如何避免这种歧义?
在C++11及之后的版本中,可以使用列表初始化语法来明确创建无参对象,比如:
Foo f{}; // 明确是对象定义,不会被解析为函数声明 Bar b{}; // 同样是对象定义尝试,但会因为构造函数被delete报错
这种写法可以彻底避免编译器把对象定义误判为函数声明的问题。
内容的提问来源于stack exchange,提问作者Joseph D.
相关产品推荐
相关产品推荐

