Essential C++
屋檐下的水滴--读书笔记系列
面向过程的编程风格 Procedural Programming
1. C++不允许改变改变reference所代表的对象,对reference的所有操作与对“reference所代表的对象”所进行的操作相同。
2. 以by reference方式传递对象当作函数参数时,复制的将是对象的地址,函数中对该对象的所有操作都相当是对传入的对象进行间接操作。
3. pointer和reference的最重要差异是,pointer可以为空,使用前一定要确保其值非0,而reference必定代表某个对象,不必作此检查。
4. 编译器无法根据函数返回值型别来区分两个具有相同名称的函数,因为返回值型别无法保证提供我们一个足以区分不同重载函数的情境。
5. 由函数指针寻址出来的函数,其调用方式和一般函数相同。
6. 可以给函数指针赋予初值,函数名称即代表了函数的地址。
7. 标准的或项目专属的头文件应用尖括号扩住;用户自行提供的头文件则使用引号。
2002-6-3
泛型编程风格 Generic Programming
1. Standard Template Library (STL) 主要由两种组件构成:容器container和泛型算法generic algorithm<通过function template技术,实现与容器及数值类型无关之功能>。
2. 容器分类:<切记:vector可以是空的,数组则否>
序列式容器sequential container: vector, list, deque……
关联式容器associative container:map, set, ……
3. iterator及const_iterator实际上是各个容器定义式内的嵌套nested 型别。
4. 使用泛型算法须#include <algorithm>,使用function object须#include <functional>。
5. function object是某种class的实体对象,该class对function call运算符进行了重载操作从而可使function object被当作一般函数来使用。令function call运算符成为inline,从而消除“通过函数指针来调用函数“时需付出的额外代价。
6. function object adapter会对function object进行修改操作。
7. 绑定配接器binder adapter <bind1nd, bind2nd> 会使bineary function object变成unary function object;negator adaper <not1, not2>会逆转function object的真伪值;另外一种有用的adapter 叫做instertion adapter <back_inserter, inserter, front_inserter>。 #include <iterator>
8. map被定义为一对数值,其中key通常是个字符串,扮演索引角色,另一个数值是value。
9. 任何一个key值在map或set内最多只有一份,若要多份相同key值,使用multimap或multiset。
完成日期:2002-6-2
基于对象的编程风格 Object-Based Programming
1.在class内部定义的member 函数被自动视为inline函数。对inline函数而言,声明在class内部或外部并无区别,同non-member inline函数一样,它应于头文件中定义。
2.Triangular t();被编译器视为一个函数定义!并不是声明或定义一个Triangular对象!
3.以某个class object作为另一个object的初值时,会发生default memberwise initialization<实际上是自动产生一个copy constructor>,可以为该class提供一个copy constructor来改变这一默认行为模式。
4.若有必要为class撰写copy constructor,则同样有必要为它撰写copy assignment operator,除非撰写copy constructor的目的仅仅是为了激活编译器实施NRV优化。
5.凡是在class主体以外定义的const member function,必须同时在声明与定义时都提供const关键字,const紧接于函数参数表之后。
6.member function返回一个指向member data的non-const reference,实际上等于将该member data开放出去,允许程序在其它地方加以修改。由于函数可以根据参数const与否 而重载,故可以提供两份定义,一份为const版本,一份为non-const版本。
8. 设计class时,鉴定其const member function是一件很重要的事情!
9. 将member data声明为mutable表明:对该member data的修改不会破坏class object的常数性。
10. 欲以一个对象复制出另一个对象,先确定两个对象是否相同是个好习惯。
11. 运算符的重载规则:不可以引入新的运算符,除了., .*, ::, ?:4个运算符,其它运算符皆可被重载;运算符的操作数operand不可改变;运算符的优先级不可改变;运算符函数的参数列中必须至少有一个参数为class型别。
12.increment和decrement运算符的前置及后置版本都可直接施行于class object其之上,编译器会自动为后置版产生一个int引数,其值必为0。
13.所谓friend,具备了与class member function相同的存取权限,可以存取class的private member。
14.只要class设计者显示提供了copy assignment operator,它就会被用来取代default memberwise copy行为。
15.当编译器在编译过程中遇到函数调用,例如lt(ival),lt可能是函数名称,可能是函数指针,也可能是一个提供了function call的function object。如果lt是个function object,编译器会在内部将此语句转化为:lt.operator(ival);
16.function call可以接受多个运算符,通常将function object当作参数传给泛型算法。
17.为了取得某个member function的地址,只需对函数名称施以取址address-of运算符,同时,函数名称之前必须先以class object运算符加以修饰,而返回型别及参数表皆不需指明,如:void (classname::*mfptr) (int) = &classname::mfname;
18.注意所谓的maximal munch编译规则,如:static vector<vector<int> > seq; 两个”>”号之间必须加有空格,否则无法成功编译!
19.pointer to member function和pointer to function的一个不同点是:前者必须通过同类的对象加以调用。.*符号是针对class object的 pointer to member selection运算符,->*符号是针对pointer to class object的pointer to member selection