赋值运算符重载的指针悬挂问题
-
对任一类X,如果用户没有自定义的赋值运算符函数,那么编译系统将自动的为其生成一个默认的赋值运算符函数,默认赋值运算符函数重载形式如下:
X&X::operator =(const X & source) { 成员间赋值 } -
若obj1和obj2是类X的两个对象,obj2已经被创建,则编译系统执行obj1=obj2时,就会调用默认的赋值运算符函数,它将对象obj2的数据成员逐一复制到对象obj1的数据成员中。
-
通常,默认的赋值运算符是可以正常工作的,但是在某些特殊情况下,如类中有指针类型时,使用默认赋值运算符会产生错误,这个错误被称为“指针悬挂”。
-
下面是一个使用默认赋值运算符函数造成的指针悬挂实例。
-
主函数里,我们用大括号将一部分代码的生存期改变了,而不是使用的注释代码。这样做的原因是为了说明指针悬挂问题。编译系统调用默认赋值函数执行s2=s1后,s1和s2都指向了同一块内存空间,这时输出s2的内容为Lin。但当s2生存期结束时,调用了析构函数释放了指针指向的空间后,造成s1指针悬挂,内存访问错误,输出乱码。(有点类似于默认复制构造函数中当有指针类型数据,复制析构后带来的内存崩溃问题。)
-
解决方法当然是自定义赋值运算符函数。
#include <iostream>
using namespace std;
//指针悬挂实例
class Student{
private:
char* name;
public:
Student(char* ptr)
{
name=new char[strlen(ptr)+1];
strcpy(name,ptr);
}
void print()
{
cout<<name<<endl;
}
~Student()
{
delete [] name;
}
};
int main()
{
Student s1("Lin");
{
Student s2("");
s2=s1;
cout<<"s2:";
s2.print();
}
s1.print();
// Student s2("");
// s2=s1;
// s2.print();
// s1.print();
return 0;
}
运行结果: