书籍:C++ Primer,C++标准程序库,Effective C++,C++ concurrency in Action, Linux多线程服务端编程,The Design and Evolution of C++
C++基础:
1. 读取数量不定的输入数据
while(std::cin >> value)
while内返回其左侧运算符,即std:cin, IO库定义了从istream向bool转换的规则,当istream作为条件时,效果是这个流的状态,有效输入(未遇到错误),条件为真,无效输入(读到文件尾,不是value变量类型), 条件为假
键盘输入文件结束符,unix Ctrl+D
2. C++是静态数据类型的语言,它的类型检查发生在编译时,编译器必须知道程序中每一个变量对应的数据类型
3. 避免依赖于实现环境的行为,比如不同机器上int类型的尺寸可能是不一样的
4. 切勿混用带符号类型和无符号类型,计算前带符号数会自动转换为无符号数,如果计算结果为负数会出现错误
5. 'A' 表示单独字符,"A" 表示字符数组A,编译器会在字符数组末尾添加空字符'\0'
6. 列表初始化,如果丢失精度,编译器会报错
7. 内置类型变量在函数内(包括main),如果不初始化是未初始化值,在所有函数外面,如果不初始化会采用默认初始化。其他类型变量如果有无参构造函数,无论函数内外均采用默认构造函数。
8. 引用不是一个对象,它是对象的别名,定义时必须初始化,且只能与相同类型的对象bind,字面值和表达式不行
但const引用是个例外,(1)在初始化常量引用时允许用任意表达式作为初始值,只要该值可以转换为引用的类型 (2)允许为一个常量引用绑定非常量的对象,字面值或表达式
9. 指针就是一个对象,实现了对其他对象的间接访问,空指针用nullptr或字面常量0来初始化,int *ptr中的*是类型修饰符,int是基本数据类型
10. 如果想在多个文件之间共享const对象,必须在变量的定义和声明之前添加extern
11. 常量表达式由数据类型和初始值共同决定。constexpr的变量类型便于由编译器来验证变量的值是否是一个常量表达式,声明为constexpr的变量一定是一个常量且必须用常量表达式初始化。
constexpr int * ptr 表示顶层const,常量指针与指针所指对象无关,constexpr修饰的指针所指的对象必须是存在固定地址中的变量(定义于所有函数体之外的对象),或者为nullptr或0
12. 类型别名:typedef 关键字声明,新标准可以用using关键字定义类型的别名 using SI=Sales_item;
13. 某个类型别名指代的是复合类型或常量,声明语句里需要特别注意,不能尝试把类型别名直接替换成它本来的样子,这里的基本数据类型是指针,是顶层const表示常量指针
typedef char *pstring; const pstring cstr = 0; // cstr是指向char的常量指针 const pstring *ps; // ps是一个指针,它指向的对象是指向char的常量指针
14. auto 定义的变量必须有初始值,编译器通过初始值来推断变量类型
15. auto一般会忽略顶层const,同时底层const会保留
const int ci = 2,&cr = ci; auto b = ci; // b是一个整数(ci的顶层const被忽略) auto c = cr; // c是一个整数(cr是ci的别名 ci的顶层const被忽略) auto d = &ci; // d是一个指向整型常量的指针(对常量对象取地址是一种底层const)
16. decltype 选择并返回表达式(操作数)的数据类型,与auto处理顶层const不同,如果表达式是一个变量,decltype返回该变量的类型(包括顶层const和引用在内)
int i=42, *p = &i, &r = i; decltype(r) b; // 错误,b是一个int & 且这里必须要初始化 decltype(r+0) c; // c是一个未初始化的int decltype(*p) d; //错误,c是int &,必须初始化
注意,指针解引用decltype的结果类型为引用类型int&,不是int,可以这样想,解引用指针可以得到指针所指的对象,而且还能给这个对象赋值。
注意,decltype((variable)) (注意是双层括号)的结果永远是引用,单括号时只有 variable 是引用时才是引用
注意,赋值会产生引用,引用的类型就是左值类型,i是int,表达式i=x的类型是int &,decltype(a=b)这里a的值没有赋值为b(即不实际计算表达式),只是返回对应的左值引用类型
17. 防止多次包含相同头文件出错,应该设置头文件保护符,#define指令把一个名字设定为预处理变量,#ifdef和#ifndef检查这个指定的预处理变量是否已经定义,当检查为真,则执行后续的操作直到#endif为止
18. string size函数的返回类型为string::size_type, 无符号类型的值,注意不应该和带符号数混用
19. 使用C++版本的C标准库头文件,因为在名为cname的头文件中定义的名字从属于命名空间std,而定义在名为.h的头文件中不是
20. range for 遍历 string
for(auto c : str) // 这里的每次迭代将str的下一个字符拷贝给c cout << c;
如果要改变字符串中的字符则需使用引用 auto &c。 更多的是使用下标运算符随机访问,它返回的是字符的引用
21. 迭代器,end尾后迭代器指尾元素的下一个位置,如果容器为空,则begin和end返回的是同一个迭代器,都是尾后迭代器
泛型编程,推荐使用迭代器遍历元素!=尾后迭代器的形式,因为并不是所有容器都可以用下标索引
cbegin和cend的迭代器类型是const_iterrator常量迭代器不能修改指向的元素
凡是使用迭代器的循环体,不要向迭代器所属的容器添加元素
22. 字符数组,当用字符串字面值初始化字符数组时,字符串结尾的空字符'\0'会占一位,const char a[6]="Demian"; // 错误,没有空间存放空字符
数组下标的类型是size_t, 机器相关的无符号类型,也可以使用range for遍历
定义在iterator头文件中的begin和end函数可以用来获取相应的数组首元素和尾后元素指针
cstring中的C风格字符串函数,传入此类函数的指针必须指向以空字符作为结束的数组
string转C风格字符串c_str()返回const char * 类型的指针
用range for处理多维数组,除了最内层的循环外,其他所有的循环的控制变量都应该是引用类型,否则编译器初始化这些变量时会自动将这些数组形式的元素转换成指向该数组内首元素的指针
23. m%n不等于0,那么结果的符号和m相同。/则不同,结果异号为负
24. 逻辑运算采用短路求值的策略,几个关系运算符不能连起来写,进行比较运算时,除非比较的对象是bool,否则不要使用bool字面值true/false作为比较对象,因为true为转换为对应非bool类型出现错误
25. 除非必须,否则不用递增递减运算符的后置版本,因为后置版本需要将原始值存储下来,如果不需要修改前的值就是一种浪费,对复杂的迭代器类型消耗巨大。
必须使用的case: *ptr++的优先级等价于*(ptr++),先+1,然后返回原始值的副本解引用
26. 处理复合表达式:(1)拿不准时最好用括号强制表达式的组合关系符合逻辑 (2)如果改变了某个运算对象的值,在表达式的其他地方不要再使用这个运算对象(否则可能会产生未定义的结果)
27. 建议仅将位运算符用于处理无符号类型,运算对象为“小整型”会自动提升为较大的整数类型
28. sizeof返回一条表达式或一个类型名字所占的字节数,利用数组大小除以单个元素大小可以得到数组元素个数
29. 逗号表达式,首先对左侧表达式求值后将结果丢弃,真正的结果是右侧表达式的值
30. 隐式类型转换被设计的尽可能避免损失精度
无符号类型不小于带符号类型,那么带符号的运算对象转换成无符号的,如果为负数,那么取模后变成正的,这大多数不是想要的结果。如果带符号类型大小大于无符号类型则无符号类型需要转换
大多数表达式中,比int类型小的整型值首先提升为较大的整数类型
31. 强制类型转换: 尽量避免强制类型转换的使用 cast_name<type>(expr)
dynamic_cast: 支持运行时类型识别
static_cast: 任何具有明确定义的类型转换,只要不包含底层const,都可以使用static_cast
const_cast: 只能改变运算对象的底层const,去掉const,不能改变表达式类型
reinterpret_cast: 有点复杂,不了解直接用很危险,它通常为运算对象的位模式提供较低层次上的重新解释(把运算对象的内容解释成另外一种类型),但存储的真实类型不变
int *ip; char *ip = reinterpret_cast<char*>(ip); // 这里pc所指的真实对象仍然是int而不是字符
32. P147 4.12 运算符优先级表
33. 右值: 指一种表达式,其结果是值而非值所在的位置
左值: 指求值结果为对象或函数的表达式,强调的是位置,并且可以作为被赋值
34. 在if、switch、while和for语句的控制结构内定义变量,定义在控制结构当中的变量只在相应语句内部可见,语句结束,变量也超出其作用范围了
35. if 或 else (while 或 for 同理) 之后必须写上花括号,确定的语句块可以避免代码的混乱不清
36.
来源:https://www.cnblogs.com/demian/p/12015805.html