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

C++临时对象生命周期结束后程序未崩溃的原因分析

为什么悬垂引用调用成员函数没有崩溃?

先看你的代码:

#include <iostream>
using namespace std;

struct Bar {
    inline void print() const { std::cout << "Bar" << std::endl; }
};
struct Foo {
    Foo() : b{} {} // 创建临时对象
    void print() const { b.print(); } // 正常运行,但我预期会崩溃
    Bar&& b;
};

int main() {
    Foo f; // 预期临时对象生命周期在此结束
    f.print(); // 正常执行 - 输出"Bar"
}

编译器给出的警告已经点出了核心问题:warning: a temporary bound to 'Foo::b' only persists until the constructor exits——你绑定到b上的临时Bar对象,在Foo构造函数执行完毕后就被销毁了,之后b就变成了悬垂引用,指向的内存已经不属于这个对象了。

那为什么调用b.print()没崩溃?这得从C++成员函数的调用逻辑说起:

  • Bar::print()是一个没有访问任何对象成员的非虚成员函数。
  • 非虚成员函数的调用本质上是编译器把对象地址作为隐式this指针传递给函数。这里的this指针指向的是原临时对象占用的内存,但因为print()里没有读取或写入该对象的任何成员(只是输出固定字符串),所以即使内存已被释放,只要这块内存还没被其他数据覆盖,函数就能正常执行。

换句话说,你只是“碰巧”没触发错误——这属于C++里的未定义行为(Undefined Behavior):标准没有规定这种情况下程序必须崩溃,它可能正常运行、可能崩溃、可能输出乱码,甚至可能做任何奇怪的事情。

如果给Bar加个成员变量试试,比如:

struct Bar {
    std::string s = "Bar";
    inline void print() const { std::cout << s << std::endl; }
};

这时再运行,很大概率会崩溃或者输出乱码,因为print()需要访问this->s,而这块内存已经被销毁,内容是无效的。

总结一下:悬垂引用本身是严重的错误,只是你的测试场景刚好没触发崩溃,但绝对不能依赖这种行为——编译器警告已经明确告诉你问题了,一定要修复它(比如把Bar&& b改成Bar b,或者确保引用指向的对象生命周期足够长)。

内容的提问来源于stack exchange,提问作者Joseph D.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 07:04:02