effective C++读书笔记

effective C++:

01条款:视C++为一个语言联邦:

effective C++里面说C++包含了C,Object-Oriented C++,Template C++和stl四种。

然而,根据最新标准,应该是以下五种:

  • is a better C
  • supports data abstraction (e.g., classes)
  • supports object-oriented programming (e.g., inheritance)
  • supports generic programming (e.g., reusable generic containers and algorithms)
  • supports functional programming (e.g., template metaprogramming, lambda functions,constexpr)

引用参考

然而,正如条款1所说,应该将其视作语言联邦,在必要的时候,选择合适的编程范式进行编程


02条款:尽量以const,enum,inline替换#define

#define指定的常量不会进入符号表,在编译错误时不会弹出宏的名字。

其次,无法跨作用域地指定常量,如指定类专属常量时,作用域外#define依然奏效

最后,由于#define展开是应用序展开,与常规的函数展开(正则序)不同,应该使用inline替代

e.g  #define multiply(a,b) a * b;   multiply(3+4, 5+ 3)的结果是3 + 4 * 5 + 3,即26


03条款:尽可能使用const

需要改变的对象不加const,其他使用const避免了错误


04条款:确定对象使用前被初始化

有一点建议:声明变量可以在前面。初始化或者定义尽量延后,在使用前不久进行


05条款:了解C++默默编写了哪些函数

C++03:default构造函数,析构函数,copy构造函数,copy assignment运算符

C++11:除了以上还有move operation


06条款:明确拒绝编译器自动生成的函数

C++03:写空定义函数

C++11:=delete对函数


07条款:为多态基类声明virtual析构函数

指针多态的对象在析构时,能够根据实际对象进行析构,选择合适的析构函数


08条款:别让异常逃离析构函数

C++析构函数中,抛异常可能导致内存泄漏,并没有完全地释放内存,应当将抛异常的代码部分移到析构函数外,并且在析构前调用它们

同理,在构造函数中也不能抛异常,因为类未完成构建,也就不知道如何析构,会出现错误,同样应当把抛异常的代码部分移到构造函数外调用


09条款:不在构造和析构过程中调用virtual函数

未必会调用derived class中的函数,此时类不变式已经被打破。


10条款:令operator = 返回一个reference to  *this

C++的=运算符就是这么规定的。所有重载必须和C++运算符中的规则匹配。


11条款:operator= 处理自我赋值

12条款:复制对象时勿忘每一个成分


13条款:对象管理资源

RAII,小心使用原始指针的pimpl模式的析构。


14条款:在资源管理类中小心copying行为

资源未必是可以复制的,不能复制的只能使用浅复制,最好还是使用引用计数的智能指针。

此外,还能够复制底部资源或者转移底部资源的拥有权(即C++11中的move语义)


15条款:在资源管理类中提供对原始资源的访问

有时APIs会要求对原始资源的范围呢


16条款:成对使用new和delete要采用相同形式

new[],delete[]配合;

new,delete配合;

placement new, placement delete配合;


17条款:以独立语句将newed对象置入智能指针

即智能指针管理资源


18条款:让接口易被使用,不易误用

良好的命名,何时的参数等等


19条款:设计class犹如设计type


20条款:以pass by reference to const替换pass by value

使用const by const提高了参数传递效率


21条款:必须返回对象时,别妄想返回reference

如果内部创建的对象,返回的reference在函数外内存已经释放了

可以返回对象副本,或者使用一个引用的对象作为函数的调用对象来作为返回值


22条款:成员变量声明为private

类的封装


23条款:宁以non-member,non-friend替换member函数

24条款:所有参数需要转换,使用non-member函数

扩展性更好,e.g类型转换的时候


25条款:考虑不抛异常的swap


26条款:尽量延后变量定义式的时间

27条款:少做转型


28条款:避免返回handles对象内部

暴露了对象内部,与封装思想相抵


29条款:为“异常安全”努力是值得的

不泄露任何资源,不允许数据败坏,


30条款:了解inlining的里里外外

插入到代码中,会使代码膨胀,应该只使用于小型函数


31条款:文件编译依存关系降至最低

尽量前置声明


32条款:public继承塑造is-a关系

33条款:避免遮掩的名称

遮掩即非virtual的父类和子类都有的同名函数,子类遮掩了父类的这个函数。


34条款:区分接口继承和实现继承

=0的使用,永远不会被实例化的类


35条款:考虑virtual函数以外的选择

template method模式,使用函数指针的strategy模式(其实现在可以使用bind,function对象来代替函数指针)


36条款:不重定义继承的non-virtual函数

也就是避免遮掩


37条款:不重定义继承而来的缺省参数

避免对父类和子类不同调用时产生不同的结果


38条款:通过复合构造出has-a

39条款:谨慎使用private继承

40条款:谨慎使用多重继承


41条款:了解隐式接口和编译器多态

模板的隐式接口即模板参数的限制(e.g能调用的子函数等等)


42条款:了解typename的双重定义

typename在模板参数中声明模板参数,也可以在模板定义内表明后面是一种类型


43条款:处理模板化基类的名称

对于模板参数是派生类,并且在此函数中调用了父类方法时,会被编译器报错,因为在编译期时不能访问该父类方法

应该在前面使用this->即指针多态或者using父类方法的作用域


44条款:参数无关的代码抽离template

45条款:成员函数模板接受所有兼容类型

46条款:类型转换为模板定义非成员函数

47条款:traits class表现类型信息

48条例:认识template模板元编程


49条款:定制new和delete

operator new无法分配内存时,调用客户的错误处理函数(new-handler),再抛出异常

50条款:new和delete的替换时机

1.检测错误(如dump)2.强化效能(自己定制内存分配器)3.收集统计数据

51条款:编写new和delete需要固守常规

52条款:写了placement new,也要写placement delete


53条款:不要轻视编译器警告

54条款:熟悉TR1

现在应该是boost,TR2了吧

cppreference




你可能感兴趣的:(读书笔记)