Timothy

链接

《More Effective C++》------ ( 3 )

2010年6月08日 05:03 | Comments(4) | Category:Reading Notes | Tags:

条款10:在constructor内组织资源泄漏。
 
(1):在constructor内初始化指针成员发生异常时,无法调用到析构,于是此成员无法会泄漏。
 
(2):避免方法,try catch,或者把这样的初始化分散到各个private成员函数中,分开捕获异常;最好的方法,把这样的成员封装成智能指针,自动析构。
 
 
 
条款11:不要让异常流出destructor。
 
(1):避免发生栈辗转机制。
 
栈辗转机制:在执行一个函数,catch到一个异常,正在处理时,又抛出一个异常,且没有捕获,传到了上层这个函数,则会发生terminate。
 
(2):要保证所有需要析构的工作都正常完成。
 
 
 
条款12:理解抛出异常和传递一个参数或者调用一个虚函数之间的区别
 
(1):调用一个函数,控制权回到调用者这里;但是抛出一个异常后,控制权不会再回到抛出地点。
 
(2):异常对象一定是以复制对象传递。
 
 
 
条款13:以引用方式传递对象
 
(1):接收到异常对象时,以写 throw; 再次抛出,而不是 throw expobj; 这样会触发再次复制。
 
 
 
条款14:小心使用异常规格( Exception specifications )
 
(1):函数在抛出一个不符合异常规格的异常时,会触发 Unexpected函数,它的缺省行为是terminate, terminate的缺省行为就是 abort.
 
(2):Exception Specifications不检查嵌套性。
 
 
 
条款15:了解异常机制带来的开销
 
 
 
--------------------------------------------------------------------------------------------------------------------------
 
-------------------------------------------------------------
 
效率Efficiency
 
 
 
条款16:牢记80-20法则
 
 
 
条款17:考虑使用Lazy evaluation( 缓式评估)
 
(1): 4个表现方面: a),引用计数,避免不需要的对象拷贝;b),对字符串的 [] 操作符,在读写时区别对待 c), 延缓读写数据库 d), 延缓计算复杂度表达式值
 
(2); 核心思想: 最 缓 的执行某些消耗较大却非必要马上执行的计算或操作,前期以各种技巧规避之。
 
 
 
条款18:分期摊还期望的计算( over-eager evaluation, 急迫式评估 )
 
(1):核心思想:  你认为某个运算或动作需要频繁的执行,则可以采用数据结构或策略高效的处理,降低每次计算的开销。
 
(2):两个例子: cache( 缓存 ) 和  prefeching( 提前读取,预先申请空间)
 
 
 
条款19:理解临时对象的来源
(1):一般有两个主要方式, 为了使函数调用成功执行的隐式转换产生对象 和 函数返回一个对象时。
 
条款20:协助完成对函数返回值的优化
(1):返回对象时,切忌不可返回 栈上对象的引用。
(2):返回对象时,先声明对象,再返回,必将触发复制构造和析构,就是临时对象效率问题,可以 constructor argument
    即  return CA( ... );  //返回一个CA对象 
    原理是: C++允许优化不出现的临时对象(此种返回,对象没有具名实际出现过) --- 返回值优化
 

 

 

《More Effective C++》------ ( 2 )

2010年6月08日 01:10 | Comments(71) | Category:Reading Notes | Tags:

 条款6:区别increment / decrement操作符的前置和后置形式

(1):prefix和postfix语法上有区别,因为他们的函数形式表面上一样的,于是实际上 postfix 是多了一个参数的,值始终为0而已。

      并且,prefix返回引用,postfix返回const对象(代表旧值,const是避免连加)。

      int& operator++() .............                ++i;

      const int operator++( int ).............   i++(0);

(2):从效率上说,prefix比postfix高;从维护上说,一般的实现版本中,postfix代码调用prefix函数来完成累加动作,这样维护 加动作 只需要维护prefix的函数。

 

条款7:千万不要重载&&, ||和,操作符

(1): &&, || 有一定的提前判断,  ,操作符表示顺序执行,返回最后一个操作的值

(2):该条款告诉你,某些operator不要重载,会破坏C++的语言特性。

不可重载的有: 

.       .*          ::            ?:

new  delete sizeof  typeid

4个cast

 

条款8:了解不同意义的new 和 delete

(1):new operator, 即new expression,    CA *p = new CA; 展开后为:  void *buffer = operator new ( size ),  在buffer上构建CA, 调用CA的构造函数

      这里的operator new 确实存在, #include <new> ( stl ), void* operator new( size_t  t );

(2):new 和 delete 对应, 分配内存并调用构造函数,  析构再删除内存。

      如果采用operator new 取得内存,在此内存上产生对象,则不要调用delete, 只需要调用析构,再free内存。 称为 placement new。

 

void *pBuffer = operator new( sizeof( CA ) );
if ( pBuffer != NULL )
{
    CA *pA = new( pBuffer ) CA();  //pA正常

    //释放方式
    //delete pA;		//错误
    pA->~CA();
    free( pBuffer );  
} 
...

 

 

(3):数组, new[ ] 和 delete[ ] 要对应, 调用的constructor 和 destructor数量跟数组的元素个数相关。

(4):new operator和delete operator属于内建操作符,不可修改其行为;但是 operator new 和 operator delete 则可修改其行为。

 

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

异常(Exception)

Exception的好处和理由:

(1):返回错误码的方式,需要函数调用者检查错误,可以被跳过或者忽略掉。而抛出exception,若未被catch,则程序会马上停止;

(2):exception发生时,栈上对象可以析构掉,其他方法无法保证。

 

 

条款9:利用Destructor避免资源泄露

(1):本条款的思想就是: 利用exception发生时,析构可以自动调用,避免内存泄露。

      容易出错的代码:

 

...
CA *pA = new pA;
pA->dosomething();
delete pA;
...

 

 若dosomething()发生异常,则delete无法执行到;

 

      正确的代码:

 

...
CAObject obj( new CA );
obj.GetPtr()->dosomething();
...

 

     用一种类似于智能指针的思想,以局部变量出现,在析构中清理资源。

     

《More Effective C++》------ ( 1 )

2010年6月02日 23:15 | Comments(0) | Category:Reading Notes | Tags: