其他章节:C++ Primer
赋值运算符的左侧运算对象必须是一个可修改的左值。
int i = 0, j = 0, k = 0; // 初始化而非赋值
const int ci = i; // 初始化而非赋值
1024 = k; // 错误:字面值是右值
i + j = k; // 错误:算术表达式是右值
ci = k; // 错误:ci是常量(不可修改的)左值
赋值运算的结果是它的左侧运算对象,并且是一个左值。结果的类型就是左侧运算对象的类型。
如果赋值运算符的左右两个运算对象类型不同,则右侧运算对象将转换成左侧运算对象的类型。
C++11允许使用花括号阔起来的初始值列表作为赋值语句的右侧运算对象。
- 如果左侧运算对象是内置类型,那么初始值列表最多只能包含一个值,且若该值转换其所占空间也不应该大于目标类型的空间。
- 对于类,赋值运算的细节由类本身决定。
- 无论左侧运算对象的类型,初始值列表都可以为空。编译器创建一个值初始化的临时量并将其赋给左侧运算对象。
赋值运算满足右结合律
赋值运算符满足右结合律,与其他二元运算符不同
int ival, jval;
ival = jval = 0; // 正确:都被赋值为0
// 先运算jval = 0,返回左侧运算对象,再执行ival = jval
对于多重赋值语句中的每一个对象,它的类型或者与右边对象的类型相同、或者可由右边对象的类型转换得到。
int ival, *pval; // ival的类型是int;pval是指向 int的指针
ival = pval = 0; // 错误:不能把指针的值赋给int
string sl, s2;
s1 = s2 = "OK"; // 字符串字面值"OK"转换成string对象
赋值运算优先级较低
赋值语句经常会出现在条件当中。因为赋值运算的优先级相对较低,所以通常需要给赋值部分加上括号使其符合原意。
int i; //更好的写法:条件部分表达得更加清晰
while ((i=get value()) != 42){
//其他处理……
}
赋值运算符的优先级低于关系运算符的优先级,所以在条件语句中,赋值部分通常应该加上括号。
相等运算符和赋值运算符
C++允许将赋值运算作为条件,这一特性会导致意想不到的后果。
if (i = j)
// 此时,if语句的条件部分把了的值赋给i,然后检查赋值的结果是否为真。如果j不为0条件将为真。然而程序的初衷很可能是想判断i和j是否相等:
if (i == j)
复合赋值运算符
+= -= *= /= %= // 算术运算符
<<= >>= &= ^= |= // 位运算符
// 任意一种复合运算符都完全等价于
a = a op b;
使用复合运算符只求值一次,使用普通的运算符则求值两次。包括:一次是作为右边子表达式的一部分求值,另一次是作为赋值运
算的左侧运算对象求值。