为何初始化全局对象的引用后,其析构函数会被调用两次?
条件表达式初始化const引用引发的对象析构异常问题
当通过条件表达式将const引用绑定到全局对象或函数返回的临时对象时,会出现循环迭代后全局对象被析构的现象,从运行输出看疑似全局对象被销毁两次。
测试代码
#include <stdio.h> #include <string> using namespace std; struct S { string name; S(const string & n) : name(n) { printf("%s(%s)\n", __func__, name.c_str()); } ~S() { printf("%s(%s)\n", __func__, name.c_str()); } void g() const { printf("%s(%s)\n", __func__, name.c_str()); } }; S f() { return S("f"); } S s("global"); int main(int argc, char ** argv) { (void)argc, (void)argv; printf("%s: begin\n", __func__); for (int i=0; i<2; i++) { const auto & z = i ? s : f(); z.g(); } printf("%s: end\n", __func__); }
运行输出
S(global) main: begin S(f) g(f) ~S(f) g(global) ~S(global) main: end ~S(global)
测试环境:GCC 8.5、14.2及在线编译器。
编辑说明:若将条件表达式替换为const auto & z = s;,编译器不会在每次循环迭代后调用其析构函数,推测条件表达式破坏了临时对象生存期延长规则且未给出警告?
编辑2:谜团已解开,因未显式定义拷贝构造函数,编译器生成了默认拷贝构造函数——条件表达式的两个分支必须返回相同类型,函数f()返回的是临时对象,因此全局对象s会被拷贝生成临时对象来匹配类型,引用实际绑定的是这个临时副本而非原全局对象。副本在每次循环迭代结束时被析构,而原全局对象在程序结束时正常析构,析构函数实际工作正常。
内容的提问来源于stack exchange,提问作者John Smith
相关产品推荐
相关产品推荐

