【读书笔记】Effective C++

来源:互联网 发布:拥有域名之后怎么建站 编辑:程序博客网 时间:2024/06/05 09:42
【Item01】视C++为一个语言联邦         C++体系包括C、Object-Oriented(面向对象编程)、Template(模板)、STL(标准模板库) 【Item02】尽量使用Enum、const、inline代替#define         a.#define:在预编译阶段采用直接替代方式,不方便调试         b.const:修饰变量、函数、指针、引用、对象         c.inline:对于短小且调用频繁的函数可以声明为内联函数,提高效率【Item03】切莫使用未初始化的变量或者对象         a.为内置类型进行手动初始化,C++不保证初始化他们         b.构造函数最好(或者一定)使用初始化列表进行初始化,而不是赋值进行初始化(提高效率)         c.成员变量初始化顺序为声明顺序,与初始化列表顺序无关【Item05】了解C++默默产生哪些函数          a.当用户未声明构造函数、赋值、复制构造函数,在需要的情况下(也就是说并不一定会生成,只是在需要建立类对象)          b.编译器会为类生成默认的构造函数、复制函数、赋值函数          c.一旦用户声明上述函数,则编译器不再自动生成。          d.编译器自动生成的赋值、复制构造函数属于浅复制,当存在指针、引用成员变量时,会导致严重问题。【Item06】若不需要编译器自动生成上述函数,应明确拒绝          a.方式-:用户自己声明赋值、复制构造函数,且权限设为private          b.方式二:定义Class UnCopy{                           private:                                UnCopy operator=(UnCopy &rhs);                      }【Item07】为多态基类定义Virtual析构函数           a.当采用多态形式  Base  *pBase = new Derived();   b.若基类析构函数为virtual:  delete  pBase;//会调用子类的析构函数,不会产生内存泄漏    若基类析构函数为non-virtual:delete  pBase;//不会调用子类的析构函数,只能删除子类中基类成员部分,会产生内存泄漏【Item08】别让异常逃离析构函数           a. try...catch捕获  【Item09】不要在构造函数中调用Virtual函数,会导致不可预期的错误          a.在子类构造函数未完成之前,其类型是不完整类型,因此在构造函数中调用virtual函数只会调用基类中virtual函数【Item10】令operator=返回引用,链式编程【Item11】在operator=中处理“自我复制”           class ClassName{      public:    //构造函数.....  private:     char* str;      }          方式一:ClassName& operator=(ClassName& const T){     if(*this==T){    return  *this; }else{     delete  str; str = T.str; return *this;    //复制操作 }  }  方式二:方式一:ClassName& operator=(ClassName& const T){      //保存旧值 char *oldStr = T.str; delete   str; str = oldStr; return *this;  }【Item12】复制对象时,切莫忘记复制基类成员变量(复制函数中调用基类的复制函数)【Item13】以对象管理资源(在对象析构函数中释放资源),避免资源泄漏           例如:智能指针   auto_ptr<ClassName> pInt(new ClassName());           auto_ptr:底层实现调用delete ptr,不能应用于数组,不能复制           shared_ptr:底层实现引用计数,支持复制,资源可以共享【Item14】在资源管理类中小心copying行为           如上auto_ptr、shared_ptr行为   浅复制和深复制的区别,内部含有指针时,只是简单复制指针,造成两个对象耦合,   内部指针指向同一个对象,当一个对象消亡,调用析构函数释放内部指针指向的对象时,   另一个对象的内部指针成为野指针,造成不可预期的错误【Item15】在资源管理类中提供对原始资源的访问方式           即是在资源管理类中提供接口,返回内部原始资源的指针或者引用【Item16】成对使用new和delete。          注意delete和delete[]区别【Item17】以独立语句将new资源指针放入资源管理类(智能指针),防止产生异常           auto_ptr<ClassName> pInt(new ClassName());//有问题,当new ClassName()产生异常时,传入参数是null指针   ClassName *pClassName = new ClassName();   auto_ptr<ClassName> pInt(pClassName);//合理做法【Item18】让接口能够被正确使用,不能被误用。          做好异常值判断,即用户传入任何值都能获得应得的行为【Item19】设计Class犹如设计Type           考虑到各种异常输入【Item20】用pass-by-reference取代pass-by-value          对于一个类对象:传值意味着一次复制构造+一次析构函数的时间成本          对于内置类型pass-by-value更合理【Item21】必须返回对象时,别妄想返回reference          局部对象在函数返回时消亡,返回引用则是无效引用  ClassName& function()  {       ClassName  tt;   //do  something;   return tt;  }//错误【Item22】将成员变量设为private,提供统一接口,增强封装性           定义setter和getter函数   越少的“人”看到内部成员,则改动时影响越小【Item23】宁以非成员、非友元函数取代成员函数【Item24】若所有参数皆需类型转换,则采用非成员函数           解决classValue*2和2*classValue问题【Item25】考虑写出一个不抛出异常的Swap函数【Item26】尽可能延后对象定义的时间(使用时再定义)【Item27】尽量少做转型操作           const_cast:去除变量const属性           static_cast:隐式转型           dynamic_cast:向下转型           reinterpret_cast:任意转型,破坏性最大【Item28】避免返回Handle指向对象内部成分【Item29】为异常安全而努力是值得的【Item30】透彻了解inline里里外外          将大多数inline限制在小型被频繁调用的函数身上,这可使日后的调试更容易,也可使代码膨胀问题最小化,使程序的速度提升机会更大化  不要只因为function template出现在头文件中,就将他们声明为inline【Item31】将文件间的依存关系降到最低【Item32】确定你的public继承塑造出is-a关系【Item33】避免遮掩继承而来的名称           derived class内的名称会遮掩base class内的名称,在public继承下从来没有人希望如此   为了让被遮掩的名称重见天日,可用using声明式或转交函数【Item34】区分接口继承和实现继承          声明一个纯虚函数目的是让子类只继承函数接口  声明非纯虚函数目的是让子类继承该函数的接口和缺省实现【Item35】考虑virtual函数以外的其他选择【Item36】绝不重新定义继承而来的non-virtual函数【Item37】绝不重新定义继承而来的缺省参数值【Item38】通过组合构造出has-a关系【Item39】明智而审慎使用private继承【Item40】明智而审慎的使用多重继承          多重继承带来对象布局不同,比单一继承复杂,他可能导致新的歧义性,以及对virtual继承的需要  virtual继承会增加大小、速度、初始化复杂度等等成本,如果virtual base class不带任何数据将是最具实用价值的情况【Item41】了解隐式接口和编译器多态  classes和templates都支持接口和多态  class而言接口是显式的,以函数签名为中心,多态则是通过virtual函数发生于运行期  template参数而言,接口是隐式的,奠基于有效表达式,多态则是通过template具现化和函数重载解析发生于编译器【Item42】了解typename的双重意义  template<class T>和template<typename T>意义相同  请使用关键字typename表示嵌套丛书类型名称;但不得在base classlist内    以它作为base class修饰符【Item43】学习处理模板化基类内的名称【Item44】将于参数无关的代码抽离template【Item45】运用成员函数模板接受所有兼容类型【Item46】需要类型转换时请为模板定义非成员函数【Item47】请使用traits class表现类型信息【Item48】认识template元编程【Item49】了解new-handler的行为【Item50】了解new和delete的合理替换时机【Item51】编写new和delete时需要固守常规
0 0
原创粉丝点击