完整阅读C++ Primer Plus
系统重新学习C++语言部分,记录重要但易被忽略的,关键但易被遗忘的。
友元、异常和其他
1、抛出异常类时,虽然catch的是一个引用,但是也会产生一次拷贝,因为当抛出异常的函数在栈解退的过程中会会调用异常类的析构函数,异常类将不复存在。
2、如果有一个异常类层次结构,应该这样排列catch块:将捕获位于层次结构最下面的异常类的catch语句放在最前面,将捕获基类异常的catch语句放在最后面。抛出异常的顺序要与catch块相反。
3、在catch语句中使用基类对象时,将捕获所有的派生类对象,但派生类特性将被剥去,因此将使用虚方法的基类版本。
4、 将dynamic_cast用于引用时,由于没有与空指针对应的引用值,因此无法使用特殊的引用值来表示失败,当请求不正确时,将引发bad_cast的异常。
5、reinterpret_cast运算符并不支持所有的类型转换,例如,可以将指针类型转换为足以存储指针的整数,但不能将指针转换为更小的整型或浮点型。另一个限制是,不能将函数指针和数据指针互相转换。
string类和标准模板库
6、使用new分配内存时,可以使用auto_ptr、unique_ptr、shared_ptr、但只有unique_ptr有使用new[]和delete[]的版本。
7、在unique_ptr为右值时,可以将其赋值给shared_ptr,模板shared_ptr包含一个显式构造函数,可以用于将右值unique_ptr转换为shared_ptr。
8、对于所有内置的算术运算符、关系运算符和逻辑运算符,STL都提供了等价的函数符(仿函数)。
9、valarray模板类重载了许多运算符,可以直接参与大多数数值运算;slice类可用作数组索引,它接受三个值初始值:起始索引、索引数、跨距。
1 valarry<double> arr(10); 2 arr[slice(1,4,3)] = 10;
slice(1,4,3)创建的对象表示选择4个索引,这可以将arr的第1、4、7、10个元素都设置为10。
10、迭代器类型
Input iterator(输入迭代器) | 读,不能写;只支持自增运算 |
Output iterator(输出迭代器) | 写,不能读;只支持自增运算 |
Forward iterator(前向迭代器) | 读和写;只支持自增运算 |
Bidirectional iterator(双向迭代器) | 读和写;支持自增和自减运算 |
Random access iterator(随机访问迭代器) | 读和写;支持完整的迭代器算术运算 |
输入、输出和文件
11、对于标准错误输出,是没有缓冲区的。
12、在使用cout时,可以使用成员函数width()设置下一次输出时的字段宽度,默认右对齐并以空格填充空白字段,当字段宽度不足时,C++不对截断输出宽度;使用成员函数fill()用来填充空白字段;使用成员函数precision()来设置浮点数输出精度;成员函数setf()与unsetf()提供了更丰富的输出格式设置方法,但使用标准控制符将更加简单。
13、对于cin的get()方法和getline()方法来说,如果没有读取到任何字符(getline()将换行符视为一个字符),则设置failbit;如果读取了最大数目的字符,但行中还有其他字符,getline()将设置failbit。
14、cin的peak()方法可以查看输入流中的下一个字符,gcount()方法可以返回最后一个非格式化抽取方法读取的字符数,putback()方法可以将字符插入到输入字符串中。
15、fstream类中的方法seekg()和seekp()分别将输入指针和输出指针移到指定的文件位置,事实上,由于fstream类使用缓冲区来存储中间数据,因此指针指向的是缓冲区中的位置,而不是实际的文件。
16、fstream类中的方法tellg()和tellp()方法分别返回输入流、输出流当前指针的位置,对于fstream对象,输入输出指针将一前一后地移动,因此它们的返回值相同。但对于使用istream对象来管理输入流,而使用ostream对象来管理同一个文件的输出流,则输入指针和输出指针将彼此独立的移动。
17、关于如何生成临时文件,使用tmpnam()可以生产TMP_NAM个不同的文件名,其中每个文件名包含的字符不超过L_tmpnam个。
18、C++库还提供了sstream族(包含ostringstream类和istringstream类),它们使用相同的接口提供程序和string对象之间的IO。
探讨C++新标准
19、新标准引入的移动语义,用来修饰六个特殊函数的default关键字,用来删除任意成员函数的delete关键字,以及使用类似初始化列表的方式在一个构造函数中使用另一个构造函数(被称为委托构造),以及使用using 类名::函数名,使基类所有的非特殊成员函数对派生类可以用(继承构造函数),以及显示声明重写(覆盖)某个虚函数的标识符override,以及禁止派生类覆盖特定的虚函数标识符final。
20、C++11引入lambda表达的主要目的是能够将类似于函数的表达式用作接受函数指针或函数符的函数的参数。
21、C++提供了多个包装器对象,用于给其他编程接口提供更一致或更合适的接口。C++11提供了包括模板bind(替代bind1st和bind2nd)、men_fn(将成员函数作为常规函数传递)和reference_wrapper(创建行为像引用但可被复制的对象)以及funtion(以统一的方式处理多种类似于函数的形式,使用模板时可减少可执行代码的规模)。
22、正确使用递归实现可变参数模板。
23、C++11增加了对并行编程的支持,以及相当多的新增库等。
附录
24、C++允许定义指向类成员(包括数据和函数)的指针,这种语法需要使用到成员解除引用运算符(* 、->*)。
25、C++11新增了alignof运算符,它接受一个类型作为参数,返回这个类型的对齐方式;noexcept关键字用于指出函数不会引发异常,它也可以用作运算符,判断表达式是否可能引发异常,不引发返回true。
26、STL提供了丰富的全局函数,包括查询,排序,复制等一系列算法。
2020年6月2日,星期二,凌晨2点01分,首次完整读完这本书,共勉。
学如逆水行舟,不进则退;心似平原放马,易纵难收。