- 理解 C/C++ 中的左值和右值 写得很好
简单定义
- 左值(lvalue, locator value) 表示一个占据内存中某个可识别得位置(地址)得对象
- 右值(rvalue), 不是左值就是右值, 不表示内存中某个可识别位置的对象的表达式。
举例:
int var;
var = 4;
赋值操作需要左操作数是一个左值。但是:
1 = var;
(var + 1) = 4;
常量4 和 var + 1 都不是左值,因此不能赋值。
又一个例子
int globalvar = 20;int& foo()
{return globalvar;
}int main()
{foo() = 10;return 0;
}
这里 foo 返回一个引用。引用一个左值,因此可以赋值给它。实际上,C++ 中函数可以返回左值的功能对实现一些重载的操作符非常重要。一个常见的例子就是重载方括号操作符 [],来实现一些查找访问的操作,如 std::map 中的方括号:
std::map<int, float> mymap;
mymap[10] = 5.6;
之所以能赋值给 mymap[10],是因为 std::map::operator[] 的重载返回的是一个可赋值的引用。
可修改的左值
const int a = 10; // 'a' 是左值
a = 10; // 但不可以赋值给它!
也并不是所有的左值都可以赋值,可赋值的左值被称为 可修改左值。
CV限定的右值
什么是CV限定?
CV限定是指const
和volatile
两个类型限定符。
一个非函数、非数组的类型T的左值可以转换为右值。 如果T不是类类型(class 定义的类)转换后的右值得类型是T得未限定CV版本。其他情况下,转化后得右值类型就是T本身。
所以这有啥用呢?
C++11 的右值引用
C++11 标准中引入了最强有力的特性就是右值引用,以及相关的 移动语义(move semantics) 概念。
这篇文章的大部分内容都在解释:左值和右值的主要区别是,左值可以被修改,而右值不能。不过,C++11 改变了这一区别。在一些特殊的情况下,我们可以使用右值的引用,并对右值进行修改。
假设我们要实现一个 整数的 vector, 我们可以这样定义
class Intvec
{
public:explict Intvec(size_t num = 0) : m_size(num), m_data(new int[m_size])};