5.3 位操作符(The Bitwise Operators)
尽量不要使用符号数进行位运算,因为符号位的处理和机器有关。
对XOR的描述真是简单明了,For each bit position, the result is 1 if either but not both operands contain 1; Otherwise, the result is 0.
输入输出标准库重载了移位操作符>>和<<用于输入和输出。
复合表达式的求值(Evaluating Compound Expressions)
这里面有两个关键词:
l Precedence
Precedence specifies how the operands are grouped.优先级规定的是操作数的结合方式
l associativity
Associativity specifies how to group operators at the same precedence level.结合性规定了具有相同优先级的操作符如何分组。
例如:
赋值操作符是右关联
ival = jval = kval = lval // right associative
(ival = (jval = (kval = lval))) // equivalent, parenthesized version
|
算数操作符是左关联
ival * jval / kval * lval // left associative
(((ival * jval) / kval) * lval) // equivalent, parenthesized version
|
5.4 赋值操作符(Assignment Operators)
让你不得不佩服,Lippman这样的大师仅仅赋值操作符(Assignment Operators)就可以讲出这么多的内容。
l 赋值运算是右关联,它的返回值是左操作数;类型为左操作数的类型(The result of an assignment is the left-hand operand, the type of the result is the type of the left-hand operand.)。
这样就好理解这样的赋值语句了:
先执行jval = 0;返回值是jval ,再执行ival = jval。
int ival, jval;
ival = jval = 0; // ok: each assigned 0
|
l 赋值操作的优先级低。
下面的条件语句返回值是true,因为先执行赋值语句,返回值是i,i大于0,因此条件语句判断为true。
下面的条件语句返回值是false,因为先执行赋值语句,返回值是i,i等于0,因此条件语句判断为false。
5.5 Increment and Decrement Operators自增和自减操作符
l 重点
前置和后置操作符
l 建议
只在必要的时候才使用后置操作符。
l 区别
前置和后置操作符的返回值是不同的,这是最重要的区别,也是理解的基础。
前置操作符:值加1,再返回。(It increments the value and returns the incremented version.)
后置操作符:必须保留原始值,(原始值加1)返回的结果是未增加的值。(The postfix operator must store the original value so that it can return the unincremented value as its result.)
l 代码
cnt—的返回值是cnt。
vector<int> ivec; // empty vector
int cnt = 10;
// add elements 10...1 to ivec
while (cnt > 0)
ivec.push_back(cnt--); // int postfix decrement
|
*iter++就是*(iter++),++操作的优先级高于*,所以先执行iter++,这个操作的返回值是iter,然后iter+1.再执行解引用操作*,这个解引用操作的操作数是返回的iter。
vector<int>::iterator iter = ivec.begin();
// prints 10 9 8 ... 1
while (iter != ivec.end())
cout << *iter++ << endl; // iterator postfix increment
|
Sizeof
?如果是返回对象的size,那么sizeof的返回值是不是和数据有关?
赋值顺序
l && 和 || 操作符计算其操作数的次序:当且仅当其右操作数确实影响了整个表达式的值时,才计算这两个操作符的右操作数。
&& and || operators specify the order in which their operands are evaluated: In both cases the right-hand operand is evaluated if and only if doing so might affect the truth value of the overall expression.
(这句话说的真是严谨。)
l 一个表达式里,不要在两个或更多的子表达式中对同一对象做自增或自减操作。
Do not use an increment or decrement operator on the same object in more than two subexpressions of the same expression.
5.11 new 和 delete 表达式(The new and delete Expressions)
new表达式返回的是一个指针,这个指针指向新分配的一个对象。
int *pi = new int; // pi points to dynamically allocated,
delete pi;
|
但是这样写就不是动态分配的指针
int i;
int *pi = &i;
delete pi; //因为pi指向的是一个local变量
|
后面的写法是不能执行delete表达式的。
由new动态创建的对象一定要执行delete来删除。否则内存就会被耗尽。
大师给了以下的建议:
l Setting the pointer to 0 after the object it refers to has been deleted makes it clear that the pointer points to no object.(一旦删除了指针所指向的对象,立即将指针置为 0,这样就非常清楚地表明指针不再指向任何对象。)
l Reading or writing to the object after it has been deleted. This error can sometimes be detected by setting the pointer to 0 after deleting the object to which the pointer had pointed.(读写已删除的对象。如果删除指针所指向的对象之后,将指针置为 0 值,则比较容易检测出这类错误。)
l Applying a delete expression to the same memory location twice. This error can happen when two pointers address the same dynamically allocated object. If delete is applied to one of the pointers, then the object's memory is returned to the free store. If we subsequently delete the second pointer, then the free store may be corrupted.(对同一个内存空间使用两次 delete 表达式。当两个指针指向同一个动态创建的对象,删除时就会发生错误。如果在其中一个指针上做 delete 运算,将该对象的内存空间返还给自由存储区,然后接着 delete 第二个指针,此时则自由存储区可能会被破坏。)