请在一个独立的 01_value_types.cpp 中手写并运行以下代码(使用 g++ 01_value_types.cpp -o value_types 编译)。这个 Demo 会用最直观的编译行为,向你展示编译器对这几种值类型的精准判定。
#include <iostream>
#include <string>
#include <utility>
// 重载函数 A:专门接收左值
void GetValueType(int& lref) {
std::cout << "🧱 编译器判定:这是一个【左值 lvalue】(有固定内存地址)\n";
}
// 重载函数 B:专门接收右值(包括纯右值和将亡值)
void GetValueType(int&& rref) {
std::cout << "🚀 编译器判定:这是一个【右值】(无地址的纯右值 或 允许被压榨的将亡值)\n";
}
int GetTemporaryInt() {
return 100; // 返回一个临时值(纯右值)
}
int main() {
std::cout << "--- 开始 C++11 值类型硬核验证 ---\n\n";
// 1. 验证左值
int x = 42;
GetValueType(x); // x 是个正经变量,有名字,能取地址 &x ➔ 触发左值重载
// 2. 验证纯右值 (prvalue)
GetValueType(42); // 42 是字面量,没名字没地址 ➔ 触发右值重载
GetValueType(GetTemporaryInt()); // 函数返回的临时 100,算完就消失 ➔ 触发右值重载
// 3. 验证将亡值 (xvalue)
// std::move 并没有移动任何东西,它的本质就是把左值 x,强制类型转换成【将亡值】!
// 告诉编译器:“这个 x 我以后不用了,它马上要死了,你可以随时移走它的资源!”
GetValueType(std::move(x)); // 强转出来的将亡值 ➔ 触发右值重载
// 4. 深度思考:右值引用变量本身,是什么值?
int&& ref = 100; // ref 是一个右值引用,绑定了右值 100
// 🚨 思考:把 ref 传给 GetValueType,会触发哪个?
// 答案是左值!因为 ref 这个“名字”本身是一直持久存在的,你能对 &ref 取地址!
std::cout << "\n【终极陷阱测试】: ";
GetValueType(ref); // ➔ 触发左值重载!
return 0;
}