您的位置:首页 > 其它

为含指针变量的类声明一个拷贝构造函数和一个赋值操作符

2012-09-27 18:02 239 查看
C++编译器会为每个类自动生成一个默认的构造函数、析构函数、赋值函数、拷贝构造函数,这当然是在你没有为你的类声明这些函数的时候。这些默认的功能函数在为你提供方便的时候,也会给你带来麻烦。

例如:

class string {
public:
string(const char *value);
~string();

...                           // 没有拷贝构造函数和operator=

private:
char *data;
};

string::string(const char *value)
{
if (value) {
data = new char[strlen(value) + 1];
strcpy(data, value);
}
else {
data = new char[1];
*data = '\0';
}
}

inline string::~string() { delete [] data; }           //注意:new 和delete 要采用相同的形式。

如果有string的两个对象,

string a("hello");
string b("world");

当b=a时,因为你自己没为类定义那些函数,所以C++编译器会提供默认的赋值函数,这个缺省的赋值操作符会执行从a的成员到b的成员的逐个成员的赋值操作,对指针(a.data和b.data) 来说就是逐位拷贝。这种情况下至少有两个问题。

第一,b曾指向的内存永远不会被删除,因而会永远丢失。这是产生内存泄漏的典型例子。

第二,现在a和b包含的指针指向同一个字符串,那么只要其中一个离开了它的生存空间,其析构函数就会删除掉另一个指针还指向的那块内存,重复析构的问题。

下面的语句:

string a("hello");                // 定义并构造 a

{                                        // 开一个新的生存空间
string b("world");            // 定义并构造 b

...

b = a;                              // 执行 operator=,    调用默认赋值函数
// 丢失b的内存,造成内存泄露。

}                                        // 离开生存空间, 调用
// b的析构函数

string c = a;                       // c.data 的值不能确定!  调用默认的拷贝构造函数
// 但是a.data 已被删除,无法进行拷贝构造。

当这类对象进行函数参数按值传递时,形参会按照缺省的拷贝构造函数进行初始化,形参拥有一个指向该对象指针的一个拷贝,当函数结束时,形参会调用析构函数,该对象的指针也被销毁。

class stack
{
public:
stack(const char *value);
~stack();
char * data;
};

stack::stack(const char *value)
{
if(value)
{
data= new char[strlen(value)+1];
strcpy(data,value);
}
else
{
data= new char[1];
*data = '\0';
}

}

inline stack::~stack()
{
delete []data;
}

void dosth(stack pstk)
{
cout<<pstk.data<<endl;
}

int main()
{
stack str("iamxczhang");

dosth(str);

}
在析构函数出设立断点,你会看到析构函数执行两次!

牢记:只要类里有指针变量就得自己写拷贝构造函数和赋值函数,但是你确定用不着这些函数时,可以把这些函数做private声明而不去实现它,这就防止了会有人去调用它们,也防止了编译器去生成它们。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐