题目
编写程序,演示普通非常量左值引用(int&)无法绑定字面量或函数返回值等临时右值;而常量左值引用(const int&)能够合法绑定临时右值,并将其生命周期自动延长至常引用的作用域结束。通过包含构造与析构打印的结构体,精确追踪临时对象被 const& 绑定后的析构时机。
输入格式:无需外部输入。
输出格式:控制台输出结构体对象的构造、绑定延长与作用域结束时的析构日志。
数据范围与约定:C++ 临时对象生命周期与引用绑定规则。
思路与算法
1. 生命周期延长规则(Lifetime Extension)
C++ 标准规定:当纯右值(临时对象)被直接绑定到 const 左值引用或右值引用时,该临时对象的生命周期将被延长,与该引用本身的生存期严格一致,避免悬垂引用。
2. 函数传参的黄金准则const T& 成为 C++ 高性能参数传递的标准姿势:既避免了传递大型对象时的按值拷贝开销,又同时兼容传入左值与临时构造的右值,且在函数内部提供了只读约束。
3. 例外陷阱
如果将常引用绑定到类成员返回的临时对象,或者函数返回了局部常引用,生命周期不会递归跨作用域延长,会导致未定义行为(Undefined Behavior)。
完整程序
#include <iostream>
#include <string>
struct Tracker {
std::string name;
explicit Tracker(std::string n) : name(std::move(n)) {
std::cout << "[构造] Tracker: " << name << "\n";
}
~Tracker() {
std::cout << "[析构] Tracker: " << name << "\n";
}
};
Tracker createTemp(std::string tag) {
return Tracker(tag);
}
int main() {
std::cout << "=== 1. 未绑定的临时对象 ===\n";
createTemp("Temp_Unbound");
std::cout << "临时对象在表达式语句结束后立即析构\n\n";
std::cout << "=== 2. 使用 const 引用绑定临时对象 ===\n";
{
// 普通引用会编译报错: Tracker& ref = createTemp("Temp_Bound");
const Tracker& boundRef = createTemp("Temp_Bound");
std::cout << "已通过 const Tracker& 绑定临时对象: " << boundRef.name << "\n";
std::cout << "作用域即将结束...\n";
} // boundRef 在此处离开作用域,被延长的临时对象在此刻析构
std::cout << "离开作用域后,临时对象已被妥善析构\n";
return 0;
}运行示例
输出:
=== 1. 未绑定的临时对象 ===
[构造] Tracker: Temp_Unbound
[析构] Tracker: Temp_Unbound
临时对象在表达式语句结束后立即析构
=== 2. 使用 const 引用绑定临时对象 ===
[构造] Tracker: Temp_Bound
已通过 const Tracker& 绑定临时对象: Temp_Bound
作用域即将结束...
[析构] Tracker: Temp_Bound
离开作用域后,临时对象已被妥善析构