关于移动构造函数将右值绑定到引用成员的技术疑问
为什么绑定右值临时的引用成员仍能输出有效值?
你的代码里存在悬垂引用的问题,输出3只是未定义行为的侥幸结果,具体拆解如下:
- 临时对象的生命周期误区
当你调用Test T(3)时,会创建一个int类型的临时对象3,用来初始化构造函数的右值引用参数_m。但注意:
- 函数参数(包括右值引用参数
_m)在函数内部是左值,你把引用成员m绑定到了_m,而非原临时对象3。 - 根据C++标准,临时对象的生命周期只会被直接绑定的引用延长,这里构造函数参数
_m绑定的临时对象,生命周期只到构造函数执行完毕为止。构造函数结束后,临时对象3就被销毁了,此时T.m变成了指向已释放内存的悬垂引用。
为什么输出3?
这是未定义行为的典型表现:被销毁的内存区域并没有被立刻覆盖,残留的旧值3刚好被读取到。但这种结果完全不可靠——换编译器、调整优化等级,或者在代码中添加其他操作,输出可能变成随机数、垃圾值,甚至直接导致程序崩溃。如何修正?
如果你想安全地使用引用成员,需要确保它指向的对象生命周期长于Test实例:
- 方案一:绑定到生命周期可控的左值
#include <iostream> class Test { public: Test(int& _m): m{_m}{} int& m; }; int main() { int val = 3; Test T(val); std::cout << T.m << std::endl; // 安全,val的生命周期覆盖T }
- 方案二:放弃引用成员,直接存储值(更推荐,避免引用带来的生命周期风险)
#include <iostream> class Test { public: Test(int _m): m{_m}{} int m; }; int main() { Test T(3); std::cout << T.m << std::endl; // 完全安全 }
内容的提问来源于stack exchange,提问作者Hedgehog
相关产品推荐
相关产品推荐

