第四章 表达式
4.1 基础
4.1.1 基本概念
左值和右值
简单归纳:当一个对象被用作右值的时候,用的是对象的值(内容)。当对象被用作左值的时候,用的是对象的身份(在内存中的位置)。
不是很理解,日后补上
4.2 算术运算符
取余运算
- m%(-n) = m%n
- (-m)%n = -(m%n)
-21 % -8 ; // -5
21 % -5 ; // 1
4.4 赋值运算符
窄化转换
可以使用花括号来对对象初始化。但是要注意,对于内置类型,如果用花括号初始化,如果存在丢失数据的风险,编译器将报错。
int k;
k = {3.14}; //错误:窄化转换
多重赋值语句
int ival, *pval;
ival = pval = 0; //错误,赋值语句会返回左侧对象,右结合律,pval=0返回了指针,无法被转换成int
4.5 递增和递减运算符
除非必须(需要用到原始值),递增递减运算符最好使用前置版本。这样可以提升性能。因为后置版本需要保存原始值,这种额外的工作在内置类型来说影响还不是很大,但是对于类型复杂的迭代器类型,这种额外的工作就消耗更大了。
对于***** 解引用运算符 和 递增递减运算符 ,递增递减运算符优先级更高。看下面一段代码,注意这种普遍写法。
auto pbeg = v.begin();
//输出元素直到遇到第一个负值为止
while(pbeg != v.end() && *beg >= 0)
cout << *pbeg++ << endl; //先把pbeg原来的值赋值给返回和解引用结合,输出当前值。然后再给pbeg递增。
4.7 条件运算符
在输出表达式中使用条件运算符
正常情况下,想实现的运算如下:
cout << ((grade < 60) ? "Fail" : "Pass") ; //输出"Fail"或"Pass"
括号没有使用好:
cout << (grade < 60) ? "Fail" : "Pass" ; //输出0或1
在这种情况下还不是错误,这里是先进行 grade < 60 比较,得到***0***或***1***。然后***cout***输出,返回一个cout对象。此时的表达式变成了:cout ? “Fail” : “Pass” ; 返回的cout的值决定着输出。
下面是括号没有使用好的错误情况:
cout << grade < 60 ? "Fail" : "Pass" ; //错误,依据优先级,从左到右,试图比较cout和60
4.8 位运算
移位运算符
***char***类型移位,会被提升成为***int***型然后再移位。
位求反运算符
***char***类型求反,会被提升成为***int***型然后再求反。
4.9 sizeof运算符
sizeof 运算对象有两种形式:
sizeof(type);
sizeof(expr);
其中有一些比较特别的:
- 对数组执行***sizeof*** 运算得到整个数组所占空间的大小,等价于对数组中所有的元素各执行一次***sizeof*** 运算,并将所得结果求和。注意,sizeof 运算不会把数组转换成指针来处理。
- 对***string***对象或***vector***对象执行**sizeof运算只返回该类型固定部分的大小,不会计算对象中的元素占了多少空间。
//Q:sizeof运算符与string对象或vector对象
void e2(){
string str = "abcdefg";
cout << "sizeof(str):" << sizeof(str) << endl; //8,不管string内容怎么变,固定部分是8B。
vector<int> a = {0,1,2,3,4,5,6,7,8,9,10};
cout << "sizeof(a):" << sizeof(a) << endl; //24,不管vector内容怎么变,固定部分是24B。
}
4.11 类型转换
4.11.3 显示转换
static_cast
任何具有明确定义的类型转换,只要不包含底层const,都可以使用***static_cast***。
//Q:类型转换探究
void e3(){
int i = 3,j = 5;
double d = static_cast<double>(j) / i; //没类型转换的结果是1,因为int/int,然后得到int型的再赋值给double
cout << d << endl;
}
const_cast
const_cast只能改变运算对象的底层const。
const char *pc;
char *p = const_cast<char*>(pc);
reinterpret_cast
reinterpret_cast 通常为运算对象的位模式提供较低层次上的重新解释。
int *ip;
char *pc = reinterpret_cast<char*>(ip);
4.12 运算符优先级表
以前学C时的记录:
单目 - 算术 - 移位 - 关系 - 逻辑 - 赋值