20110410-左值和右值

本文详细解释了左值和右值的概念及其在程序中的应用。左值通常指变量,可以出现在赋值语句的左右两边;而右值通常指具体的数值,仅能出现在赋值语句的右侧。此外还探讨了它们在操作符使用上的限制。
  • 左值可以出现在赋值语句的左边或右边,也就是说左值可以当右值使用。
  • 右值只能出现在赋值语句的右边,不能出现在赋值语句的左边。

 

  • 左值表示程序中必须有一个特定的名字引用到这个值。
  • 右值表示程序中没有一个特定的名字引用到这个值。

 

  • 变量是左值,因此可以出现在赋值语句的左边。
  • 数字字面值是右值,因此不能被赋值。

 

  • 实际上,左值是一个存储地址,也就是一块内存存储数据所要操作的地址。
  • 右值是一个具体的数据或者数值,也就是该内存存储的数据内容。

 

  • 只有左值和右值都是单一变量的时候二者才可以相互交换位置,因为变量具有固定的内存地址。

 

  • 有些操作符,如赋值,要求其中的一个操作数必须是左值。
### 左值的基本概念 在 C++ 中,左值(lvalue)(rvalue)是表达式(expression)的分类,它们的核心区别在于是否具有持久的身份(identity)可寻址性。左值通常表示一个具有名称、可被取地址的对象,而表示一个临的、通常无法取地址的- 左值可以出现在赋表达式的左侧或侧,例如变量、数组元素、解引用的指针等。 - 通常是临,例如字面量、函数返回的临对象、表达式的结果等,它们通常无法被直接修改或取地址。 ### 左值引用与引用 C++ 中引入了两种引用类型来绑定左值: 1. **左值引用**:使用 `&` 声明,绑定到左值左值引用常用于避免不必要的拷贝操作,例如传递大对象使用引用传递。 ```cpp int x = 10; int& ref = x; // ref 是左值引用,绑定到左值 x ``` 2. **引用**:使用 `&&` 声明,绑定到引用是 C++11 引入的特性,主要用于实现移动语义完美转发。 ```cpp int x = 10; int&& ref = 42; // ref 是引用,绑定到 42 int&& ref2 = std::move(x); // std::move(x) 将左值 x 转换为 ``` ### 左值的区别 1. **生命周期与持久性**: - 左值通常具有较长的生命周期,它们是命名的对象,可以通过名称访问修改。 - 通常是临对象,生命周期较短,通常在表达式结束后立即销毁。 2. **绑定规则**: - 非常量左值引用只能绑定到非常量左值,不能绑定到常量左值。 ```cpp int val1 = 10; const int val2 = 10; int val3 = 10; int& lrval1 = val1; // 正确:非常量左值引用非常量左值 int& lrval2 = val2; // 错误:非常量左值引用常量左值 int& lrval3 = val1 + val3; // 错误:非常量左值引用非常量 int& lrval4 = 10; // 错误:非常量左值引用常量(字面量常量) ``` - 引用可以绑定到,但不能绑定到左值,除非使用 `std::move` 显式转换。 3. **移动语义**: - 引用的引入使得移动语义成为可能。移动语义允许将资源从临对象()转移到新对象,避免不必要的拷贝操作。 - 例如,`std::vector` 的移动构造函数可以将临对象的内部缓冲区直接转移给新对象,而不是进行深拷贝。 4. **函数参数传递**: - 在函数参数传递中,左值引用引用的使用会影响参数的处理方式。引用参数在函数内部被视为左值,因此需要再次使用 `std::forward` 或 `std::move` 来保持其性质。 ### 示例代码 以下是一些示例代码,展示了左值的用法: #### 左值引用示例 ```cpp int main() { int x = 10; int& ref = x; // 左值引用绑定到左值 x ref = 20; // 修改 x 的 return 0; } ``` #### 引用示例 ```cpp #include <iostream> #include <utility> int main() { int x = 10; int&& ref = 42; // 引用绑定到 42 int&& ref2 = std::move(x); // 将左值 x 转换为 std::cout << "ref: " << ref << ", ref2: " << ref2 << std::endl; return 0; } ``` #### 移动语义示例 ```cpp #include <iostream> #include <vector> class MyClass { public: std::vector<int> data; MyClass(int size) : data(size, 0) {} MyClass(MyClass&& other) noexcept : data(std::move(other.data)) {} // 移动构造函数 }; int main() { MyClass obj1(1000000); MyClass obj2 = std::move(obj1); // 使用移动构造函数 return 0; } ``` ### 总结 左值的区别在于它们的表达式类型、生命周期以及绑定规则。左值引用引用的引入使得 C++ 在资源管理性能优化方面更加灵活。通过移动语义,引用可以有效地避免不必要的拷贝操作,提高程序的效率。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值