左值、右值、可修改左值、不可修改左值

本文详细解释了C语言中l-values和r-values的概念,包括它们的区别、使用场景以及如何通过const关键字区分不可修改的左值与可修改的左值。文章还讨论了数组名作为不可修改的左值的特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Assignment: l-values and r-values

Some languages use the idea of l-values and r-values. Lvalues are values that have addresses being programmatically accessible to the running program (e.g., via some address-of–operator like "&" in C/C++), meaning that they are variables or dereferenced references to a certain memory location. Rvalues can be lvalues (see below.) or non-lvalues—a term only used to distinguish from lvalues. Consider the C expression (4 + 9). When executed, the computer generates an integer value of 13, but because the program has not explicitly designated where in the computer this 13 is stored, the expression is an rvalue. On the other hand, if a C program declares a variable x and assigns the value of 13 to x, then the expression (x) has a value of 13 and is an lvalue.

In C, the term lvalue originally meant something that could be assigned to (coming from left-value, indicating it was on the left side of the assignment operator), but since 'const' was added to the language, this now is termed a 'modifiable lvalue'.由const关键字修饰的左值属于不可修改的左值,其值不可修改,
eg: 辨别常指针与常量的指针:
char * const p;
char const * p;
const char *p;
上述三个有什么区别?
char* const p; //p为只读指针。
char const *p;//(*p)值只读的指针。
const char *p; //和char const *p意思相同。

数组名是不可修改的左值
注意:有一样操作只能在指针里进行而无法在数组中进行,那就是修改它的值。数组名是不可修改的左值,它的值是不能改变的。
<think>好的,用户现在问的是关于左值的问题。我需要先回顾一下C++中的左值的概念,以及它们的区别应用场景。用户可能希望了解如何区分它们,以及在实际编程中如何使用,特别是引用移动语义相关的部分。首先,我应该明确左值的定义。左值通常指有持久状态的对象,可以取地址,比如变量、返回左值引用的函数调用等。则是临时的,不能被取地址,比如字面量、临时对象或者返回引用的函数调用。然后,我需要考虑用户可能需要的代码示例,比如如何定义引用,移动构造函数移动赋运算符的实现,以及完美转发。这些例子能帮助用户理解如何在实际中使用这些概念。接下来,用户的问题可能涉及到C++11引入的移动语义,这可以优化资源管理,避免不必要的拷贝。比如,使用std::move将左值转换为,从而调用移动构造函数而不是拷贝构造函数,提升性能。 另外,完美转发也是一个重要概念,允许函数模板将参数以原有的类别传递给其他函数。这需要使用std::forward通用引用(引用模板)来实现。我需要确保代码示例清晰,注释详细,解释每个部分的作用。同时,要注意常见的错误,比如在移动后使用源对象,或者错误地使用引用。最后,用户可能对相关的高级主题感兴趣,比如万能引用、移动语义与异常安全的关系,或者如何优化性能。这些问题可以作为后续的问题提出,引导用户深入理解。</think>以下是C++左值(lvalue)(rvalue)的详细解析及代码示例: ```cpp #include <iostream> #include <vector> #include <utility> // for std::move // 左值判断工具函数 void check_value_category(int&) { std::cout << "lvalue reference\n"; } void check_value_category(int&&) { std::cout << "rvalue reference\n"; } // 移动语义示例类 class Resource { std::vector<int> data; public: Resource() = default; // 拷贝构造函数(左值版本) Resource(const Resource& other) : data(other.data) { std::cout << "Copy constructor\n"; } // 移动构造函数(版本) Resource(Resource&& other) noexcept : data(std::move(other.data)) { std::cout << "Move constructor\n"; } // 移动赋运算符 Resource& operator=(Resource&& other) noexcept { data = std::move(other.data); std::cout << "Move assignment\n"; return *this; } }; // 完美转发示例 template<typename T> void wrapper(T&& arg) { // 万能引用 process(std::forward<T>(arg)); // 完美转发 } void process(const Resource&) { std::cout << "Processing lvalue\n"; } void process(Resource&&) { std::cout << "Processing rvalue\n"; } int main() { // 基础示例 int a = 10; // a是左值 int&& rref = 42; // 42是 check_value_category(a); // 输出lvalue reference check_value_category(10); // 输出rvalue reference check_value_category(rref); // 输出lvalue reference(具名引用是左值) check_value_category(std::move(a)); // 输出rvalue reference // 移动语义示例 Resource res1; Resource res2 = res1; // 调用拷贝构造函数 Resource res3 = std::move(res1); // 调用移动构造函数 // 完美转发示例 Resource res4; wrapper(res4); // 转发左值 wrapper(Resource()); // 转发 } ``` **关键概念解释**: 1. **左值(lvalue)**: - 有持久状态的对象 - 可以取地址(如变量、函数返回的左值引用) - 可以出现在赋运算符的侧 2. **(rvalue)**: - 临时对象或即将销毁的对象 - 不能取地址(如字面量、临时对象、函数返回的引用) - 主要分为纯(prvalue)将亡(xvalue) 3. **引用**: - 使用`&&`声明(如`int&& rref`) - 只能绑定到(但具名引用本身是左值) - 主要用途:实现移动语义完美转发 4. **移动语义**: - 通过`std::move`将左值转换为引用 - 避免不必要的拷贝操作(如大对象的传递) - 需要实现移动构造函数移动赋运算符 5. **完美转发**: - 保持参数原始的类别(左值/) - 使用`std::forward<T>`万能引用(`T&&`) - 常用于泛型编程工厂模式 **典型应用场景**: 1. 优化容器操作(如`vector::push_back`的重载) 2. 实现资源管理类(如智能指针) 3. 构建高性能字符串处理(如string的移动操作) 4. 实现线程安全的数据转移
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值