/*
 * 理解左值和右值
 *
 *
 * 为什么要关心这个?
 * 1. 有助于理解C++结构,搞明白编译器的错误和警告
 * 2. C++ 11中引入了右值引用,理解左值右值是前提
 *
 */


/*
 * 简单的定义:
 *
 * 左值 - 在内存中具有可标识位置的对象
 * 右值 - 任何不是左值的对象
 */


//左值的例子:
int i;        // i是左值
int* p = &i;  // i的地址是可标识的
i = 2;    // 内存的内容改变

class dog;
dog d1;   // 用户定义类型的左值
            // C++代码中大多数变量是左值


//右值的例子:
int x = 2;        // 2是右值
int x = i+2;      // (i+2)是右值
int* p = &(i+2);  // Error,地址不可标识
i+2 = 4;     // Error 地址不可标识
2 = i;       // Error

dog d1;
d1 = dog();  // dog()是用户定义类型的右值

int sum(int x, int y) { return x+y; }
int i = sum(3, 4);  // sum(3, 4) 是右值

//右值: 2, i+2, dog(), sum(3,4), x+y
//左值: x, i, d1, p


//引用 (或者说左值引用):
int i;
int& r = i;

int& r = 5;      // Error,引用不能赋值为右值(还是左值),需要可标识的地址    这里理解为5是常量   只能赋值给常量的引用。

//例外:常量左值引用可以赋值为右值
const int& r = 5;   //


// 函数中的例子
int square(int& x) { return x*x; }
square(i);   //  OK
square(40);  //  Error

//解决方法:
int square(const int& x) { return x*x; }  // square(40) and square(i) work



/*
 * 左值可以用来生成右值
 */
int i = 1;
int x = i + 2; 

int x = i;


/*
 * 右值可以用来生成左值
 */
int v[3];
*(v+2) = 4;


/*
 * 误解1:函数或运算符总是产生右值
 */
int x = i + 3;  
int y = sum(3,4);

int myglobal ;
int& foo() {
   return myglobal;
}
foo() = 50;

// 更常见的例子:
array[3] = 50;  // 操作符[] 几乎总是返回左值



/*
 * 误解2:左值都是可以修改的
 *
 */
const int c = 1;  // c是左值
c = 2;   // Error, 但是c不能被修改



/*
 * 误解3:右值不能被修改
 */
i + 3 = 6;    // Error,内置类型的确不行
sum(3,4) = 7; // Error

// 对于用户定义类型不成立
class dog;
dog().bark();  // dog()是右值,bark() 可能修改dog对象的状态



/*
 * 总结
 *
 * 1. 每个C++表达式生成一个左值或右值
 * 2. 如果表达式有一个可以标识的内存地址,则它是左值;否则,是右值
 */
posted on 2020-10-19 08:45  学习记录园  阅读(205)  评论(0编辑  收藏  举报