条款11: 为需要动态分配内存的类声明一个拷贝构造函数和一个赋值操作符
这个条款的原因在哪里呢?
就是如果你创建一个类,什么都不做,那么类会给你创建一个默认构造函数,默认析构函数,默认拷贝函数和默认赋值函数。
所以出问题就出在默认上面去了,尤其是默认拷贝函数和默认赋值函数出的问题最多。
默认拷贝函数会怎么做呢,对于a=b,它会将b中的成员逐位拷贝给另一个a,如果通过指针动态分配内存,则仅仅将指针的值赋给a。
这会导致至少两个问题:
第一,b曾指向的内存永远不会被删除,因而会永远丢失。这是产生内存泄漏的典型例子。第二,现在a和b包含的指针指向同一个字符串,那么只要其中一个离开了它的生存空间,其析构函数就会删除掉另一个指针还指向的那块内存。
看下面代码:
[cpp]
#include
#include
#include
using namespace std;
class MyString
{
public:
MyString(const char* value);
~MyString();
friend ostream& operator << (ostream& os,MyString &c);
private:
char *data;
};
MyString::MyString(const char* value)
{
if(value){
data = new char[strlen(value)+1];
strcpy(data,value);
}
else{
data = new char[1];
data = '\0';
}
}
ostream& operator << (ostream& os,MyString &c)
{
os<
}
MyString::~MyString()
{
delete []data;
}
int main()
{
MyString a("hello");
{
MyString b("world");
b = a;
}
MyString c = a;
cout<
}
#include
#include
#include
using namespace std;
class MyString
{
public:
MyString(const char* value);
~MyString();
friend ostream& operator << (ostream& os,MyString &c);
private:
char *data;
};
MyString::MyString(const char* value)
{
if(value){
data = new char[strlen(value)+1];
strcpy(data,value);
}
else{
data = new char[1];
data = '\0';
}
}
ostream& operator << (ostream& os,MyString &c)
{
os<
}
MyString::~MyString()
{
delete []data;
}
int main() } 看到输出的结果是这样的 MyString::MyString() MyString::MyString(MyString &myString) } MyString & MyString::operator= (const MyString &myString) 这里需要注意几点:
{
MyString a("hello");
{
MyString b("world");
b = a;
}
MyString c = a;
cout<
#a #a
Aborted (core dumped)
可以看到c得不到正确的值,同时析构函数调用的时候出现崩溃的问题。
所以,如果你会调用拷贝构造函数和赋值函数,那么一定要显示的声明他们,否则将他们定义为私有的。
那么下面就看看如何显示的声明他们,如下
[cpp]
MyString::MyString()
{
data = NULL;
}
MyString::MyString(MyString &myString)
{
if (this == &myString)
{
return;
}
else
{
if(myString.data != NULL)
{
data = new char[strlen(myString.data)];
strcpy(data,myString.data);
}
else
{
data = new char[1];
data = '\0';
}
}
}
MyString & MyString::operator= (const MyString &myString)
{
if (this == &myString)
{
return *this;
}
else
{
delete []data;
if(myString.data != NULL)
{
data = new char[strlen(myString.data)];
strcpy(data,myString.data);
}
else
{
data = new char[1];
data = '\0';
}
}
return *this;
}
{
data = NULL;
}
{
if (this == &myString)
{
return;
}
else
{
if(myString.data != NULL)
{
data = new char[strlen(myString.data)];
strcpy(data,myString.data);
}
else
{
data = new char[1];
data = '\0';
}
}
{
if (this == &myString)
{
return *this;
}
else
{
delete []data;
if(myString.data != NULL)
{
data = new char[strlen(myString.data)];
strcpy(data,myString.data);
}
else
{
data = new char[1];
data = '\0';
}
}
return *this;
}
1 MyString c = a; 实际上调用的是MyString::MyString(MyString &myString), 而不是重载 =号的函数。
你可以用vs或者gdb来单步调试。原