最近重读了《Effective C++》,对一些复杂的知识点会专门写文章分析,这里将一些小的知识点总结一下,但不会涵盖书里的所有内容。
条款2
良好的用户自定义类型的特征是它尽量能与内置类型兼容
宁可用编译器替换预处理器
尽量多用const,而不是宏定义.宏属于模块化的设计概念,会破坏封装性
常量可能比
#define
产生较小量的代码.如果类需要用到多个常量,不要用const数组,而是改用枚举
对于宏形式的函数,最好用内联函数取代
条款3
- 希望迭代器指向的东西不可改动,需要
const_iterator
条款4
永远在使用对象前初始化.对于
int x;
,有些编译器会将x初始化为0,有些却不会,所以无论之后有没有用到x,都要先对其初始化,比如int x=0;
成员变量如果是const或引用,它们只能用成员列表初始化的方法进行初始化
条款5
编译器自动生成的析构函数不是virtual,除非这个类的基类的析构函数是virtural
编译器自动生成的4个函数都是public
如果基类的copy构造函数和copy运算符是private,编译器不会为派生类生成它们
派生类的copy构造函数可以尽量不定义
条款6
定义uncopyable类是很好的禁止使用copy构造函数和copy运算符的方法,它的析构函数可以不是virtual,派生类不必以public继承它,也没有成员变量,也可以用于多重继承
类的不可拷贝特性是可以继承的,例如凡是继承自uncopyable的类都不能使用copy构造函数和赋值运算符
条款7
如果基类析构函数不声明为virtual,析构时不会调用派生类的析构,可查看原因分析
如果一个类不做基类,就不要有virtual析构函数或其他虚函数,因为虚指针会增大类的体积。 反过来,只要一个类做基类,就要有virtual函数
当类至少有一个虚函数时,为它声明virtual析构函数,否则编译器有报警
对于抽象类,可以将析构函数声明为pure virtual析构函数
条款8
- 析构函数里不要抛出异常,否则会导致不确定行为
条款9
构造函数和析构函数中都不要调用virtual函数,因为基类构造时,virtual函数不会下降到派生类阶层,或者说此时的virtual函数还不是virtual函数
对于存在多个构造函数的情况,为避免代码重复,要把同样的代码放到一个函数里,比如init
条款10
- 赋值运算符(包括
+= -= *=
)的返回最好是return *this
,这符合STL等标准库的风格
条款12
自定义copy构造函数或运算符时,需要复制所有的成员变量,如果少复制了,编译器不会报警或报错
派生类的copy构造函数或运算符,无法像平时那样对基类的private成员变量赋值,因为无法访问private的变量,只能显式调用基类的operator =, 比如: Base::operator=(obj);
条款15
- 多使用智能指针shared_ptr,它可以返回原始指针,显式方法是get()函数,隐式方法是取指针操作符->
条款16
- new和delete必须配对,[]必须都有或都没有。千万避免new没有[],delete有[],这会导致程序不停运行析构函数
条款18
有时的形参可以用wrapper类型,而不是内置类型
保证接口的一致,比如STL容器都有个size的成员函数
可以让一些返回指针的函数返回智能指针,比如工厂函数
条款21
- 函数内返回对象时,不要返回其引用。因为引用指向局部变量,而局部变量在函数退出前销毁,所以会出现无定义行为。
条款22
成员变量应该都是private,将它们隐藏在函数接口的背后,如果放到public,直接使用成员变量会降低封装性。如果破坏了成员变量,会破坏太多的客户码
成员变量的封装性和成员变量的内容改变时破坏的代码量成反比
protected变量被消灭时,所有用到它的派生类的代码都要破坏,所以封装性也很差
条款24
若函数参数都要进行类型转换,应该使用非成员函数
成员函数的反面是非成员函数,不是friend函数,friend应该尽量避免
条款26
如果某个类的对象没有用到,就不应该声明,否则运行构造和析构函数都会耗费成本
对象初始化用构造函数比=运算符的效率高
对变量定义后应马上初始化,然后马上使用,中间不要隔太远
变量定义在循环内比外面更好,后者造成作用域更大,对程序维护性不好
条款27
代码中尽量避免dynamic_cast,它会降低效率
避免连续的cast转型,尤其是dynamic_cast
条款32
public继承是一种
is-a
的关系,每一个派生类的对象也是基类的对象程序的错误最好能在编译期检测出来,而不是运行期
条款34
public继承涉及到函数接口继承和实现的继承
纯虚函数实际上是可以提供定义的,这个用法比较罕见,知道即可
虚函数使派生类继承了其缺省实现,但这可能造成危险
条款36
- 不要重新定义继承而来的non-virtual函数,虽然没有错误,但违反了
is-a
原则,这种情况下干脆不要使用public继承