《Effective C++》学习总结(条款11 - 15)

条款11:在operator= 中处理“自我赋值”

1.“自我赋值”发生在对象被赋值给自己的时候
2.加一个“证同测试”使具有“自我赋值安全性”
3.精心安排的语句可以使代码具有“异常安全性”(自动获得“自我赋值安全性”):在复制构造之前别删除原指针
4.copy-and-swap技巧(见条款29),核心在于将*this数据与copy的复件版本进行交换操作
5.请记住:
  • 确保当对象自我赋值时operator=有良好的行为。其中的方法包括比较 “赋值的来源对象”“赋值的目标对象” 的地址(即2中的证同测试)、精心周到的语句顺序(即3)、以及copy-and-swap技巧。

  • 确定任何函数如果操作一个以上的对象,而其中多个对象是同一个对象时,其行为仍然正确。

 

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

1.如果你为class添加一个新的成员变量,那么必须要同时修改所有相应的copying函数(包括copy构造函数与任何非标准形式的copy assignment运算符重载函数)
2.当你需要为“derived class撰写copying函数”时,必须很小心地复制其bash class成员,如果涉及到private成员无法访问,应该让derived class的copying函数调用相应的base class函数。
3.当你编写一个copying函数,请确保:
  • 复制所有local成员变量;

  • 调用所有base class内适当的copying函数;

4.请记住:
  • copying函数应该确保复制“对象内的所有成员变量”及“所有base class成分”

  • 不要尝试以一个copying函数实现另一个copying函数。应将共同的重复代码放进第三个函数中(一般是private且常被命名为init)并由它们共同调用。

 

第三章:资源管理

所谓资源就是一旦你使用了它,当你不在使用它时,必须将它还给系统。

条款13:以对象管理资源

1.资源取得时机便是初始化时机,资源释放时期最好在析构期间(手动释放总是会出现各种各样的问题,不稳定)
2.前半边想法:把资源放进对象内,我们便可依赖C++的析构函数自动调用机制确保资源被正确释放
3.后半边想法:管理对象运用析构函数确保资源被正确释放
4.请记住:
  • 为防止资源泄漏,请使用RAII(Resource Acquisition Is Initialization——资源取得时机便是初始化时机) 对象,他们在构造函数中获得资源并在析构函数中释放资源。

  • 两个常被使用的RAII classes分别是tr1::shared_ptrauto_ptr。前者通常是较佳选择,因为其copy行为比较直观。若选择auto_ptr,复制动作会使它(被复制物)指向null

 

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

并不是所有资源都是heap-based,所以需要建立自己的资源管理类

1.一个一般化的问题:当一个RAII对象被复制,会发生什么事呢?
2.方案一:禁止复制——见条款6: 继承一个将copying操作声明为private的uncopyable类
3.方案二:对底层资源使用“引用计数法(reference-count)”
  • 有的时候我们希望保有资源,直到它的最后一个使用者被销毁,这种情况下复制RAII对象时,应该将资源的“被引用数”递增,例如tr1::shared_ptr,然而其缺省行为是:当引用次数为0时删除其所指物,也即当没有指向任何对象时,自动删除该智能指针。
  • 但是,shared_ptr允许指定“删除器”(deleter),当引用次数为0时会自动被调用的函数或函数对象。
4.方案三:复制底部资源
  • 复制资源管理对象时,进行“深度拷贝”(不论是指针或其所指内存都会被制作出一个复件)
5.方案四:转移底部资源的拥有权
  • 如果在某种情况下需要确保只用一个RAII对象指向一个未加工资源,这时资源的拥有权就会从被复制物转移到目标物,这也是auto_ptr的复制意义(见条款13)
6.请记住:
  • 复制RAII对象必须一并复制它所管理的资源,所以资源的copying行为决定RAII对象的copying行为
  • 普遍而常见的RAII class copying行为是:抑制copying、施行引用计数法。不过其他行为也都可能被实现

 

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

1.在资源管理类时,需要一个get()函数,其功能是将RAII对象转换为其所含原始资源,包括显示与隐式转换
  • 显式转换:对于智能指针——shared_ptrauto_ptr都提供一个get成员函数,用于执行显式转换,它会返回智能指针内部的原始指针的复件。对于不使用智能指针的情况 RAII class可以为这个问题提供一个显式转换函数(见P71),与智能指针中的get类似;
  • 隐式转换:对于智能指针,其重载了operator->operator*,允许隐式转换至底部原始指针,通过operator来访问资源。而对于不使用智能指针的情况,就需要RAII class提供一个隐式转换函数;
  • 通常来说,显式转换更加安全,但使用起来没有隐式转换方便,而隐式转换会增加错误发生的机会。
2.请记住:
  • APIs 往往要求访问原始资源(raw resources),所以每一个RAII class应提供一个“安全取得其所管理之资源”的方法;
  • 对原始资源的访问可能经由显式转换或隐式转换。一般而言显式转换比较安全,但隐式转换对客户比较方便。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值