You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何初始化全局对象的引用后,其析构函数会被调用两次?

条件表达式初始化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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 09:25:15