《Effective c++》阅读回忆一

01 视c++为一个语言联邦

c++以c为基础, 对比c 多了面向对象(class,继承,多态,封装,虚函数等),模版template泛型编程,以及stl template 程序库。

02 尽量以const,enum,inline替代#define

宏定义只是简单替换,不做类型安全性检测,容易发生无法预知的错误。且define不重视作用域,无法定义一个class专属常量。

单纯常量用const或enum替换;而不想让别人获得一个指针或引用指向某个整数常量,enum可以实现这个约束。

函数用inline替换。

03 尽可能使用const

const在指针后限制指针为常量,可以修改指针指向的值;同理在指针前限制数据为常量,可以修改指针指向的地址。

const可以修饰class里的static ,non-static成员变量,函数;可以修饰class外全局或namespace作用域中的常量,修饰函数,文件,区块作用域中的对象。

函数返回一个常量值,可以减少调用者错误造成的意外,例如operater * 返回常量对象。

const成员函数:增强class接口可读性;使操作const对象成为可能。

当const和non-const成员函数有着实质等价实现时,令non-const版本调用const版本可避免代码重复。

04 确定对象被使用前已先被初始化

对象使用之前对其初始化,内置类型需手动初始化;

自定义对象初始化责任在构造函数;区分初始化和赋值。采用初始化值列表是初始化;赋值操作需要额外先调用类成员默认构造函数,再调用拷贝赋值操作,初始化值列表直接调用拷贝构造函数,效率更高。base class先于derived class初始化。

static对象初始化:

static对象全局定义、namespace、class、file作用域内为non-local static对象,函数内为local static对象。

定义于不同编译单元内的non-local static对象的初始化次序无明确定义;而这在有依赖关系的设计里可能出现未知问题;可以将每个non-local static对象搬到专属函数内,返回一个引用指向包含的对象,non-local static 被local static对象替换,单例模式实现。

 

05 c++默默编写了哪些函数

构造函数,析构函数,拷贝构造函数,拷贝赋值函数

拒绝为class生成拷贝赋值函数(类中有引用对象,常量对象);引用不可被修改,const对象不可被修改。

06 不想使用编译器自动生成的函数,就该明显拒绝

不支持拷贝,不需要生成拷贝构造函数和拷贝赋值函数。

自己定义二者为private 且没有定义(避免被成员函数或友元函数调用)或者继承uncopyable 基类。

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

派生对象由一个base class指针删除,如果base class没有virtual析构函数会发生未知的结果,派生对象析构函数没有被调用,而导致派生成分没有被销毁。产生局部资源泄露

只为多态基类声明virtual 析构函数,不是所有base class都声明virtual 析构函数。

08 别让异常逃离析构函数

析构函数里异常如果不处理,可能导致外层程序异常终止,而一些资源没有完全释放。解决方案,析构函数接受异常中止程序(abort),或者吞下异常。额外提供普通函数给客户调用执行(关闭等操作)

09 绝不在构造和析构过程中调用virtual函数

base class先于派生类构造,所以在base class构造函数里调用virtual函数是不会下降到derived class这层。base class构造期间,virtual函数不是virtual函数。

析构函数也是一样的,先进行derived class的析构,等到运行base class的析构函数时,derived class对象的成分已经呈现未定义值,所以进入base class的析构函数时被看待为base class的对象比较合理;包括virtual函数和dynamic_cast也是这样看待处理。

解决构造和析构函数调用virtual的方案,采取derived class向上传值。

10 令operator = 返回一个引用指向*this

支持实现赋值,为了和所有内置类型,stl提供的类型保持一致。

11 在operator =中处理自我赋值

由于别名的缘故,很可能出现自我赋值的情况出现。如果operator=里不处理自我赋值的情况,很可能把目标值删除,而出现持有一个已删除的指针而导致程序未知结果。

处理方案先判断是否自我赋值,而后处理;但是同样还需要考虑异常安全性,一般会采用复制原指针内存,new新内存,删除原指针内存。这样如果new 新内存失败 原指针指向内存仍被保留。还有一个copy and swap的方案。

12 复制对象时勿忘其每一个成分

主要是实现copy 构造函数和copy 赋值操作符,要确保新加的每一个成分都被拷贝。

保证每个local变量被copy;同时保证base class的每个成分被copy,调用base class适当的copying函数。

copy构造函数调用copy 赋值操作符无意义,等于给一个尚未构造好的对象赋值;

copy赋值操作符调用copy构造函数不合理,对一个已经存在的对象再次构造。

可以将copy构造函数和copy赋值操作符相同的部分提取一个新的init函数,供二者调用。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值