### 5.4. 赋值操作符

The left-hand operand of an assignment operator must be a nonconst lvalue. Each of these assignments is illegal:

```     int i, j, ival;
const int ci = i;  // ok: initialization not assignment
1024 = ival;       // error: literals are rvalues
i + j = ival;      // error: arithmetic expressions are rvalues
ci = ival;         // error: can't write to ci
```

Array names are nonmodifiable lvalues: An array cannot be the target of an assignment. Both the subscript and dereference operators return lvalues. The result of dereference or subscript, when applied to a nonconst array, can be the left-hand operand of an assignment:

```     int ia[10];
ia[0] = 0;    // ok: subscript is an lvalue
*ia = 0;      // ok: dereference also is an lvalue
```

The result of an assignment is the left-hand operand; the type of the result is the type of the left-hand operand.

The value assigned to the left-hand operand ordinarily is the value that is in the right-hand operand. However, assignments where the types of the left and right operands differ may require conversions that might change the value being assigned. In such cases, the value stored in the left-hand operand might differ from the value of the right-hand operand:

```     ival = 0;        // result: type int value 0
ival = 3.14159;  // result: type int value 3
```

Both these assignments yield values of type int. In the first case the value stored in ival is the same value as in its right-hand operand. In the second case the value stored in ival is different from the right-hand operand.

#### 5.4.1. 赋值操作的右结合性

Like the subscript and dereference operators, assignment returns an lvalue. As such, we can perform multiple assignments in a single expression, provided that each of the operands being assigned is of the same general type:

```     int ival, jval;
ival = jval = 0; // ok: each assigned 0
```

Unlike the other binary operators, the assignment operators are right associative. We group an expression with multiple assignment operators from right to left. In this expression, the result of the rightmost assignment (i.e., jval) is assigned to ival. The types of the objects in a multiple assignment either must be the same type or of types that can be converted (Section 5.12, p. 178) to one another:

```     int ival; int *pval;
ival = pval = 0; // error: cannot assign the value of a pointer to an int
string s1, s2;
s1 = s2 = "OK";  // ok: "OK" converted to string
```

The first assignment is illegal because ival and pval are objects of different types. It is illegal even though zero happens to be a value that could be assigned to either object. The problem is that the result of the assignment to pval is a value of type int*, which cannot be assigned to an object of type int. On the other hand, the second assignment is fine. The string literal is converted to string, and that string is assigned to s2. The result of that assignment is s2, which is then assigned to s1.

#### 5.4.2. 赋值操作具有低优先级

Inside a condition is another common place where assignment is used as a part of a larger expression. Writing an assignment in a condition can shorten programs and clarify the programmer's intent. For example, the following loop uses a function named get_value, which we assume returns int values. We can test those values until we obtain some desired valuesay, 42:

```     int i = get_value();  // get_value returns an int
while (i != 42) {
// do something ...
i = get_value(); }
```

The program begins by getting the first value and storing it in i. Then it establishes the loop, which tests whether i is 42, and if not, does some processing. The last statement in the loop gets a value from get_value(), and the loop repeats. We can write this loop more succinctly as

```     int i;
while ((i = get_value()) != 42) {
// do something ...
}
```

The condition now more clearly expresses our intent: We want to continue until get_value returns 42. The condition executes by assigning the result returned by get_value to i and then comparing the result of that assignment with 42.

 The additional parentheses around the assignment are necessary because assignment has lower precedence than inequality. 在赋值操作上加圆括号是必需的，因为赋值操作符的优先级低于不等操作符。

Without the parentheses, the operands to != would be the value returned from calling get_value and 42. The true or false result of that test would be assigned to iclearly not what we intended!

##### 谨防混淆相等操作符和赋值操作符

The fact that we can use assignment in a condition can have surprising effects:

```     if (i = 42)
```

This code is legal: What happens is that 42 is assigned to i and then the result of the assignment is tested. In this case, 42 is nonzero, which is interpreted as a true value. The author of this code almost surely intended to test whether i was 42:

```     if (i == 42)
```

Bugs of this sort are notoriously difficult to find. Some, but not all, compilers are kind enough to warn about code such as this example.

## Exercises Section 5.4.2

 Exercise 5.11: What are the values of i and d after the each assignment: 请问每次赋值操作完成后，i 和 d 的值分别是多少？ ``` int i; double d; d = i = 3.5; i = d = 3.5; ``` Exercise 5.12: Explain what happens in each of the if tests: 解释每个 if 条件判断产生什么结果？ ``` if (42 = i) // . . . if (i = 42) // . . . ```

#### 5.4.3. 复合赋值操作符

We often apply an operator to an object and then reassign the result to that same object. As an example, consider the sum program from page 14:

```     int sum = 0;
// sum values from 1 up to 10 inclusive
for (int val = 1; val <= 10; ++val)
sum += val; // equivalent to sum = sum + val
```

This kind of operation is common not just for addition but for the other arithmetic operators and the bitwise operators. There are compound assignments for each of these operators. The general syntactic form of a compound assignment operator is

C++ 语言不仅对加法，而且还对其他算术操作符和位操作符提供了这种用法，称为复合赋值操作。复合赋值操作符的一般语法格式为：

```     a op= b;
```

where op= may be one of the following ten operators:

```     +=   -=   *=   /=   %=   // arithmetic operators
<<= >>=   &=   ^=   |=   // bitwise operators
```

Each compound operator is essentially equivalent to

```     a = a op b;
```

There is one important difference: When we use the compound assignment, the left-hand operand is evaluated only once. If we write the similar longer version, that operand is evaluated twice: once as the right-hand operand and again as the left. In many, perhaps most, contexts this difference is immaterial aside from possible performance consequences.

## Exercises Section 5.4.3

 Exercise 5.13: The following assignment is illegal. Why? How would you correct it? 下列赋值操作是不合法的，为什么？怎样改正？ ``` double dval; int ival; int *pi; dval = ival = pi = 0; ``` Exercise 5.14: Although the following are legal, they probably do not behave as the programmer expects. Why? Rewrite the expressions as you think they should be. 虽然下列表达式都是合法的，但并不是程序员期望的操作，为什么？怎样修改这些表达式以使其能反映程序员的意图？ ``` (a) if (ptr = retrieve_pointer() != 0) (b) if (ival = 1024) (c) ival += ival + 1; ```