代码改变世界

析构函数领悟

2013-08-08 23:27  居安  阅读(231)  评论(0编辑  收藏  举报

析构函数顿悟的灵感是在类String中闪现的:

class String
{
public:
String(const char *str = NULL); // 通用构造函数
String(const String &another); // 拷贝构造函数
~ String(); // 析构函数
String & operater =(const String &rhs); // 赋值函数
private:
char *m_data; // 用于保存字符串
};

String::String(const char *str)
{
if ( str == NULL ) //strlen在参数为NULL时会抛异常才会有这步判断
{
m_data = new char[1] ;
m_data[0] = '/0' ;
}
else
{
m_data = new char[strlen(str) + 1];
strcpy(m_data,str);
}

}

String::String(const String &another)
{
m_data = new char[strlen(another.m_data) + 1];
strcpy(m_data,other.m_data);
}


String& String::operator =(const String &rhs)
{
if ( this == &rhs)
return *this ;
delete []m_data; //删除原来的数据,新开一块内存
m_data = new char[strlen(rhs.m_data) + 1];
strcpy(m_data,rhs.m_data);
return *this ;
}
String::~String()
{
delete []m_data ;
}


开始写我们的程序了
String * pStr = new String;
....
delete String;

分析:
在new String的时候,先给pStr分配内存,注意了,这个阶段只是为成员m_data开辟一段内存,
而这里要特别特别注意的是m_data只是一个指向char* 的指针,所以这时候分配的内存也就4个字节(它是
指针而已);接下来就是构造函数,构造函数调用的默认参数的构造函数,即将m_data赋值为一个NULL。
假如在操作过程我们调用了其他给pStr赋值的函数,m_data就不再指向NULL而是指向一个实在的内存。这里
有点绕,这么说吧。new String执行后,带默认参数的构造函数执行。完后,m_data指向一个NULL。但是这
个意思是说:m_data是一个指针变量,其地址加入为0xffffffff,而这个地址里放的内容却是NULL(如果初始
化调用复制或者赋值构造函数,地址0xffffffff存放的内容是另外一个地址,假如是0xeeeeeeee,这个地址
0xeeeeeeee里放的是一串字符串的起始地址);
当我们执行delete pStr的时候,首先调用析构函数,析构函数是释放0xeeeeeeee为首地址的字符串所
占用的内存;析构函数执行完之后才释放0xffffffff地址的内存,它就是指针m_data。如果我们析构函数
什么也不做,那么就会造成0xeeeeeeee处的字符串所占用内存未被释放...而m_data却被释放了,这样的后
果就是我们永远也找不到字符串那里的内存了,我们把抽屉钥匙给丢了。