五、了解c++默默编写并调用那些函数 

class Empty()
{
};

//等同于
class Empty
{
public:
Empty() // 默认构造函数
{
}
Empty(const Empty& rhs) //拷贝构造函数
{
}
~Empty() // 析构函数
{
}
Empty&oprator=(const Empty& rhs) // 赋值运算符
{
}
}

注意:编译器产生的析构函数是非虚的析构函数

六、不想使用编译器自动生成的函数,就应该明确拒绝如果想阻止拷贝行为,可以将相应成员函数声明为private并且不予实现

//Uncopyable .h
#pragma once
class Uncopyable
{
public:
Uncopyable();
~Uncopyable();

private:

Uncopyable(const Uncopyable& unCopy);

Uncopyable& operator=(const Uncopyable&);
};
//Uncopyable.cpp
#include "Uncopyable.h"

Uncopyable::Uncopyable()
{
}

Uncopyable::~Uncopyable()
{
}

Uncopyable::Uncopyable(const Uncopyable& unCopy)
{

}

Uncopyable& Uncopyable::operator=(const Uncopyable&)
{
Uncopyable newUncopy;

return newUncopy;
}

总结
如果想阻止拷贝行为,可以将相应成员函数声明为private并且不予实现

七、多态基类声明virtual析构函数 

1、带有多态性质的基类,应该声明一个虚析构函数。如果类带有任何虚函数,
那么这个类就应该有一个虚析构函数。
否则在父类指针指向子类对象的情况下,通过操作父类指针,可能无法释放子类对象
2、类的设计目的如果不是作为基类使用,或者不是为了多态性那么就不应该声明虚析
构函数
否则,对象体积会增加
补充:标准string是不带虚析构函数的
    1、构造顺序 基类构造函数、对象成员构造函数、派生类本身的构造函数  
    2、析构顺序 派生类本身的析构函数、对象成员析构函数、基类析构函数(与构造顺序正好相反) 

八、别让异常逃离析构函数
    两个方法:
    1、阻止异常从析构函数里传播出去,强迫程序结束
 

try
{

}
catch
{
abort();
}


   在Catch里记录异常信息,然后继续运行
   2、双保险策略
    封装一个释放函数,由用户释放,如果释放成功,那么在析构函数中不做处理
    然后再析构函数中,做方法一的处理

九、绝不在构造析构过程中调用virtual函数 
    
    在derived对象的base class构造期间,对象的类型是base class而不是 derived class
    
十、令operator= 返回 reference to *this
    现在string,vector,complex,std::shared_ptr等标准库类型的赋值运算符都返回*this