绑定临时对象的引用生命周期问题——是Visual C++的Bug吗?
构造函数下临时对象生命周期不延长的原因解析
你碰到的问题核心是:聚合初始化和自定义构造函数在临时对象生命周期延长规则上有本质区别。
为什么标准示例能正常运行
标准里的代码用的是聚合初始化:
struct S { int mi; const std::pair<int,int>& mp; }; S a { 1, {2,3} };
根据C++标准,当在聚合初始化中用临时对象直接初始化类的引用成员时,这个临时对象({2,3}构造的std::pair)的生命周期会被延长至引用成员mp的生命周期结束——也就是和a的生命周期一致。这完全符合你提到的“被引用绑定的临时对象生命周期持续至引用生命周期结束”的规则。
自定义构造函数后出问题的根源
当你给S添加自定义构造函数后,初始化逻辑变成了:
S p{ Pair() };
这里的Pair()是临时对象,它先绑定到构造函数的形参const Pair& p。根据C++的规则:
- 临时对象绑定到函数形参时,生命周期只延长到构造函数调用结束(也就是
S的构造函数执行完的瞬间)。 - 你的成员
mp是绑定到构造函数的形参p,而非直接绑定到原始临时对象。构造函数执行完毕后,形参p被销毁,对应的临时对象也随之析构,此时mp就成了悬垂引用。后续调用p.print()能输出1 2只是内存未被覆盖的巧合,本质属于未定义行为(UB)。
一句话总结:只有当引用直接绑定到临时对象时,生命周期才会延长;通过函数形参间接绑定的话,生命周期不会传递到成员引用上。
验证与结论
你代码里~Pair在S p{ Pair() }后立刻输出,已经证明临时对象在构造函数结束后就被析构了。如果想让临时对象和S实例同生命周期,要么回到聚合初始化(保持S为聚合类型,即不要自定义构造函数),要么放弃引用,改为直接存储对象实例。
内容的提问来源于stack exchange,提问作者zdf
相关产品推荐
相关产品推荐

