第四章 - 表达式
位运算符和强制类型转换两部分没有详细看
1. 算术运算符
-
(m/n)*n + m%n
的求值结果与m
相等; -
除了
-m
导致溢出的特殊情况,其他时候-
(-m)/n
和m/(-n)
都等于-(m/n)
, -
m%(-n)
等于m%n
, -
(-m)%n
等于-(m%n)
-12 % -8 = -5 21 % -5 = 1
-
2. 逻辑与 &&
和 逻辑或 ||
运算符
2.1 短路求值(short-circuit evaluation)
- 对于逻辑与 运算符来说, 当且仅当左侧运算对象为真时才对右侧运算对象求值
- 对于逻辑或 运算符来说, 当且仅当左侧运算对象为假时才对右侧运算对象求值
2.2 相等性测试与布尔字面值
if (val == true) {/* ... */ }; // 只有当 val 等于1时2条件才为真, 等价于
if (val == 1 {/* ... */ }; // 比较前编译器会首先把 true 转换成 val 的类型
- 进行比较运算时,除非比较的对象是布尔类型,否则不要使用布尔字面值
true
和false
作为运算对象
3. 递增和递减运算符
3.1 前置 和 后置
-
前置: 首先将运算对象加1 (或减1) , 然后将改变后的对象作为求值结果
-
后置: 也会将运算对象加1 (或减1), 但是求值结果是运算对象改变之前那个值的副本
-
除非必须,否则不用递增递减运算符的后置版本
int i = 0, j; j = ++i; // j = 1, i = 1 j = i++; // j = 1, i = 2
3.2 在一条语句中混用解引用和递增运算符
// 输出 v 中的元素直到遇到第一个负值为止
auto pbeg = v.begin();
while (pbeg != v.end() && *pbeg >= 0)
cout << *pbeg++ << endl; // 首先将 pbeg 的值加1, 然后解引用加1前的值
cout << *iter++ << endl;
要比cout << *iter << endl; ++iter;
简洁,也更少出错
4. 条件运算符
-
嵌套条件运算符
// 成绩在90分以上得到“high pass”,在60分以下得到“fail”,其他为“pass” finalgrade = (grade > 90) ? "high pass" : (grade < 60) ? "fail" : "pass";
cond?expr1:expr2;
首先求cond
的值, 如果条件为真, 对expr1
求值并返回该值; 否则对expr2
求值并返回该值- 条件运算符的优先级低于
<<
5. 位运算符 略
6. sizeof
运算符
6.1 基本概念
-
sizeof
运算符返回一个表达式或一个类型名字所占的字节数,满足右结合律,所得的值是一个size_t
类型sizeof (type) sizeof expr // 返回表达式结果类型的大小,不实际计算运行对象的值
6.2 sizeof expr
Sales_data data, *p;
sizeof(Sales_data); // 存储 Sales_data 类型对象所占的空间大小
sizeof data; // data 的类型大小,等价于上一条语句
sizeof p; // 指针 p 所占的空间大小
sizeof *p; // p 所指的对象所占的空间大小,同 sizeof(Sales_data)
sizeof data.revenue; // Sales_data 中 revenue 成员对应类型所占的空间大小
sizeof Sales_data::revenue; // 同上一条语句
sizeof
的优先级与*
运算符的优先级一样,所以表达式按照从右向左的顺序组合,其等价于sizeof (*p)
- 在
sizeof
的运算对象中解引用一个无效指针任然是一种安全行为,因为指针实际上并没有被真正使用
sizeof
运算符的结果
对象或表达式类型 | 结果 |
---|---|
char | 1 |
引用 | 被引用对象所占空间的大小 |
指针 | 指针本身所占空间的大小 |
解引用指针 | 指针所指向对象所占空间的大小,指针无需有效 |
数组 | 整个数组所占空间的大小 |
string 或 vector | 返回固定部分的大小,不会计算对象中的元素占用的空间 |
constexpr size_t sz = sizeof (ia)/sizeof(*ia); // 返回 ia 的元素数量
7. 逗号运算符
// 将从 size 到1的值赋给 ivec 的元素
vector<int>::size_type cnt = ivec.size();
for (vector<int>::size_type ix = 0; ix != ivec.size(); ++ix, --cnt)
ivec[ix] = cnt;
- 逗号运算符(comma operator)中含有两个运算对象,按照从左向右的顺序一次求值。首先对左侧的表达式求值,然后将求值结果丢弃,逗号运算符真正的结果是右侧表达式的值
8. 类型转换 略
8.1 显示转换
-
static_cast
int i = 3, j = 5; double slope = static_cast<double>(j) / i; // 强制转换以进行浮点数除法
-
const_cast
只能改变运算对象的底层const
const char *pc; char *p = const_cast<char*>(pc); // 去掉 const 性质(cast away the const)
- 只有
const_cast
能改变表达式的常量属性
- 只有