notes/ch04.md
C++:当一个对象被用作右值的时候,用的是对象的值(内容);int i = f1() + f2()
f1() + f2(),再计算int i = f1() + f2()。但是f1和f2的计算先后不确定bool b=true;
bool b2=-b; //仍然为true
//b为true,提升为对应int=1,-b=-1
//b2=-1≠0,所以b2仍未true
vector<string> text;
for(const auto &s: text){
cout<<s;
}
ival = jval = 0;等价于ival = (jval = 0);a = a op b;j = ++i,先加一后赋值j = i++,先赋值后加一优先使用前置版本,后置多一步储存原始值。(除非需要变化前的值)
*iter++等价于*(iter++),递增优先级较高
auto iter = vi.begin();
while (iter!=vi.end()&&*iter>=0)
cout<<*iter++<<endl; // 输出当前值,指针向前移1
简介是一种美德,追求简洁能降低程序出错可能性
ptr->mem等价于(*ptr).mem
注意.运算符优先级大于*,所以记得加括号
条件运算符(?:)允许我们把简单的if-else逻辑嵌入到单个表达式中去,按照如下形式:cond? expr1: expr2
可以嵌套使用,右结合律,从右向左顺序组合
finalgrade = (grade > 90) ? "high pass"
: (grade < 60) ? "fail" : "pass";
//等价于
finalgrade = (grade > 90) ? "high pass"
: ((grade < 60) ? "fail" : "pass");
输出表达式使用条件运算符记得加括号,条件运算符优先级太低。
用于检查和设置二进制位的功能。
<<)或者向右移(>>),移出边界外的位就被舍弃掉了。~)(逐位求反)、与(&)、或(|)、异或(^)有符号数负值可能移位后变号,所以强烈建议位运算符仅用于无符号数。
应用:
unsigned long quiz1 = 0; // 每一位代表一个学生是否通过考试
1UL << 12; // 代表第12个学生通过
quiz1 |= (1UL << 12); // 将第12个学生置为已通过
quiz1 &= ~(1UL << 12); // 将第12个学生修改为未通过
bool stu12 = quiz1 & (1UL << 12); // 判断第12个学生是否通过
位运算符使用较少,但是重载cout、cin大家都用过
位运算符满足左结合律,优先级介于中间,使用时尽量加括号。
size_t的常量表达式。sizeof并不实际计算其运算对象的值。sizeof (type),给出类型名sizeof expr,给出表达式int ia[10];
// sizeof(ia)返回整个数组所占空间的大小
// sizeof(ia)/sizeof(*ia)返回数组的大小
constexpr size_t sz = sizeof(ia)/sizeof(*ia);
int arr[sz];
从左向右依次求值。
左侧求值结果丢弃,逗号运算符结果是右侧表达式的值。
设计为尽可能避免损失精度,即转换为更精细类型。
int类型小的整数值先提升为较大的整数类型。unsigned intwchar_t,char16_t,char32_t提升为整型中int,long,long long ……最小的,且能容纳原类型所有可能值的类型。p143
static_cast:任何明确定义的类型转换,只要不包含底层const,都可以使用。 double slope = static_cast<double>(j);
dynamic_cast:支持运行时类型识别。
const_cast:只能改变运算对象的底层const,一般可用于去除const性质。 const char *pc; char *p = const_cast<char*>(pc)
只有其可以改变常量属性
reinterpret_cast:通常为运算对象的位模式提供低层次上的重新解释。
type expr
p147