自定析构意味着也要自定拷贝和赋值,自定拷贝意味着要自定赋值
一、需要析构意味着拷贝和赋值
如果自定义析构意味着有指针及其指向的动态内存,采用系统合成的拷贝和赋值将会默认共享动态内存,一旦一个对象离开其作用域,将会致使delete运算符多次释放同一块内存。
类使用指针管理内存,如下:
class HasPtr
{
public:
HasPtr(const string &s=string()):ps(new string(s),i(0)){}//参数中分配动态内存
private:
~HasPtr(){delete ps;}//涉及到动态内存必须自定义析构delete这部分内存
string * ps;
int i;
};
ps实现了对new string的管理。如果用户不自定义拷贝和赋值,编译器将会默认拷贝指针本身,拷贝不会对动态内存进行拷贝。下面这个例子能够告知为什么需要定义拷贝和赋值:
{
HasPtr a;//构造
HasPtr b=a;//拷贝构造,ok!b对象也有一个指针指向a对象动态内存
HasPtr c;
c=b;//拷贝赋值,ok! c对象也有一个指向a对象动态内存
}
当对象a离开其定义域,调用析构函数进行delete动态内存,成功删除了!接着轮到对象b析构,再次调用析构函数delete已经析构的a中动态内存,这就有问题了,这部分内容已经不存在了,因此是一个严重的设计错误;同理c也将会析构一次,同样是出错。
二 、需要拷贝也需要赋值拷贝定义了拷贝应该完成的操作,如序列号+1实现每一个对象都有一个独一序列号,如果没有封住赋值是不是实现不了了?没错,所以拷贝也要赋值。