Effective C++ 5

 通过default构造函数出一个对象再对他赋值比直接在构造时指定赋值 差。

比如

string str("honey~");和

string str; str="honey~";效率就不一样。

接下来讲循环时的初始化,

/*

class A;

A a;

for(int i=0;i<n;i++)   //1次构造,1次析构,n次赋值。

{a=**;}

*/

class A;

for(int i=0;i<n;i++)  //n次构造,n次析构

{

   A a(**);

}

//综上,下面的情况好。

 

转型分为旧式转型和新式转型。

旧式转型: (T) expression

新式转型:

1.const_cast<T>(expression)  cast away the constness

将对象的常量性移除

2.dynamic_cast<T>(expression) safe downcasting

唯一不能用旧式转型实现的转型动作。不过可能耗费重大运行成本的动作。

3.reinterpret_cast <T>(expression) 低级转型

例:int*->int

4.static_cast<T>(expression) 强迫隐式转换。

例:non-const  -> const ,int->double

     pointer-to-base  ->pointer-to-derived

     void*  -> typed 指针

    

现在运用旧式转型符的时机是调用explicit构造函数。

 

 

handle:reference,指针,迭代器。

函数不要返回一个指向访问级别较低的成员函数。因为会降低封装性。

成语函数返回对象内部的handle可能会使dangling。

 

下面来看异常:

异常安全函数保证:

1.基本承诺:异常不出错即可能出于任何合法状态。

2.强烈保证:异常返回前一状态。

3.不投掷保证:不跑出异常。

 

如int f() throw();   //不是说不抛出异常,而是只要抛出异常,就导致严重错误。

 

动态分配不成功就 bad_alloc异常。

如果一个系统中有一个函数不具备异常安全性,则整个系统不具备异常安全性。

 

封装,异常安全性。

 

inline函数

1.免除调用成本

2.如果函数体过大,则会换页行为和降低指令高速缓存装置的击中率。

3.对比函数本体和函数调用所产生的代码长度。

4.因为inlining是编译期行为,所以要在头文件中。

5.template通常也 是inline但不全是。

//此实例为了证明构造函数和析构函数最好不要inline class Base { public: ... private: string bm1,bm2; }; class Derived { public: Derived(){} //看起来是空的。 private: stirng dm1,dm2,dm3; }; Derived::Derived() { Base::Base(); try{dm1.string::string();} catch(...) { Base::~Base(); throw; } try{dm2.string::string();} catch(...) { dm1.string::~string(); Base::~Base(); throw; } try{dm3.std::string::string();} catch(...) { dm2.string::~string(); dm1.string::~string(); Base::~Base(); throw; } }

 

pimpl idiom 将实现放入一个类,在接口类中定义一个智能指针指向实现类,从而达到与实现细目分离。

 

你可能感兴趣的:(Effective C++ 5)