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

为何返回字符串字面量的引用会触发Segmentation fault?

问题分析:悬垂引用与临时对象生命周期差异

先还原两段代码

第一段(触发崩溃的代码)

#include <iostream>
#include <string>

const std::string& f() {
    return "abc";
}

std::string&& g() {
    return "xyz";
}

int main() {
    const std::string& s1 = f();
    std::string&& s2 = g();
    std::cout << s1 << std::endl; // 未定义行为,可能侥幸运行
    std::cout << s2 << std::endl; // 触发Segmentation fault
    return 0;
}

第二段(正常运行的代码)

#include <iostream>
#include <string>

int main() {
    const std::string& s = "abc";
    std::string&& t = "xyz";
    std::cout << s << std::endl;
    std::cout << t << std::endl;
    return 0;
}

崩溃原因

第一段代码的核心问题:悬垂引用

  • 函数f返回const std::string&时,字符串字面量"abc"会被隐式转换为临时std::string对象,函数返回的是这个临时对象的引用。根据C++规则,该临时对象的生命周期仅持续到函数调用表达式结束,也就是f()执行完成后,临时对象就会被销毁。后续s1绑定的是一个已销毁的对象,属于悬垂引用,访问它是未定义行为(可能侥幸运行,也可能崩溃)。
  • 函数g返回std::string&&时,同样会先构造临时std::string对象,返回的是这个临时对象的右值引用。临时对象同样在g()调用结束后销毁,s2成为悬垂引用,后续访问时刚好触发内存访问错误,导致段错误。

两段代码的差异:临时对象生命周期的延长规则

C++有一条关键规则:当临时对象被const左值引用或右值引用直接绑定时,临时对象的生命周期会被延长到与引用变量的生命周期一致。

  • 第二段代码中,const std::string& s = "abc"和std::string&& t = "xyz"都是直接将引用绑定到临时构造的std::string对象,因此临时对象的生命周期被延长到main函数结束,访问时对象仍然有效,所以能正常运行。
  • 第一段代码中,引用绑定的是函数返回的引用,而非直接绑定临时对象。函数返回的引用指向的临时对象已在函数返回时销毁,生命周期延长规则不适用,因此引用变成悬垂。

内容的提问来源于stack exchange,提问作者Alexey Starinsky

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 08:45:40