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

三元运算符与直接函数调用场景下的C++对象生存期延长问题

为什么我的C代码在MSVC 2019 C14中崩溃,而其他编译器运行正常?

先来看你的代码:

#include <iostream>
#include <string>
#include <type_traits>
struct A{
    ~A(){std::cout << "killed '" << a <<"\n";}
    int a = 3;
};
template<typename T>
void foo(T&& r){
    // Is r still valid here???
    std::cout << "Running: " << r.a << "\n";
}
int main() {
    A* a = new A{3};
    foo(true ? A{4} : *a);
}

你提到的现象很典型:在GCC/Clang环境中输出符合预期,但MSVC 2019 C++14模式下程序崩溃,核心疑问是临时对象的生存期是否被正确延长。

先给结论:你的代码完全符合C++14标准,应该触发生存期延长,MSVC的崩溃是编译器实现的bug。

下面一步步拆解原因:


1. 条件表达式的结果是什么?

你的代码里,true ? A{4} : *a这个条件表达式的两个分支:

  • A{4}是prvalue(纯右值,即临时对象)
  • *a是lvalue(左值,指向堆上的A实例)

根据C++14标准,当条件表达式的两个操作数分别是prvalue和lvalue时,lvalue分支会被隐式转换为prvalue(也就是拷贝构造一个临时A对象),最终整个表达式的结果是一个prvalue临时对象。因为你的条件是true,实际生效的是A{4}这个prvalue临时对象。


2. 右值引用绑定的生存期延长规则

C++标准明确规定:当prvalue被用来初始化右值引用(或const左值引用)时,临时对象的生存期会被延长到该引用的生存期结束。

在你的代码中,foo是模板函数,传入prvalue时,模板参数T会被推导为A,因此参数r的类型是A&&(右值引用)。这个引用绑定到了条件表达式生成的A{4}临时对象,按照标准,这个临时对象的生存期应该覆盖整个foo函数的执行过程——也就是说,foo里访问r.a是绝对安全的,不会出现悬空引用。


3. 为什么MSVC会崩溃?

这是MSVC 2019在C++14模式下的一个已知实现问题(bug):它没有正确处理条件表达式生成的prvalue绑定到右值引用时的生存期延长逻辑,导致临时对象在foo函数执行前就被销毁了,此时r变成了悬空引用,访问r.a自然会引发崩溃。

你可以尝试切换到MSVC的C17或更高版本标准,这个问题大概率会被修复——因为C17对prvalue的临时物化规则做了调整,间接修复了这类边界场景的生存期处理问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 14:42:28