1,
定义两个对象:
String a("Hello");
String b("Word");
如下所示:
[img]http://dl.iteye.com/upload/attachment/251536/e9c6a62b-29c7-347b-8fcd-7be387c1af50.png[/img]
执行b=a;后,变为:
[img]http://dl.iteye.com/upload/attachment/251538/75a0f0ad-a308-3827-8671-4c50e7810e1a.png[/img]
这样的状况至少存在两个问题:
(1)b原先指向的内存没有被释放掉,内存泄露.
(2)a和b的指针指向相同的字符串,当其中一个离开生存空间,其destructor会删除内存,另外一个悬垂指针.
如:
特别注意:String c=a;
这句话调用copy constructor.导致a和c指向同一个地方,这样那个地方会被删除两次.
2,只要程序中有pass-by-value的动作,就会调用copy constructor.
void doNothing(String localString) {}
String s = "The Truth Is Out There";
doNothing(s);
这里s会产生一个副本,函数调用完成后,副本释放,导致s内含指针被删除.
而当s离开作用域,又会对相同的地方再次删除,其行为未定义.
3,解决之道:
(1)如果class拥有任何指针,那么撰写自己的copy constructor和assignment operator.
将指针所指数据结构复制,保证每个对象拥有属于自己的一份拷贝,或者实现某种引用计数策略.
(2)如果你的class不会执行copy或assignment动作,那么将其声明为private,并且不要定义.
4,自己给出的代码:
定义两个对象:
String a("Hello");
String b("Word");
如下所示:
[img]http://dl.iteye.com/upload/attachment/251536/e9c6a62b-29c7-347b-8fcd-7be387c1af50.png[/img]
执行b=a;后,变为:
[img]http://dl.iteye.com/upload/attachment/251538/75a0f0ad-a308-3827-8671-4c50e7810e1a.png[/img]
这样的状况至少存在两个问题:
(1)b原先指向的内存没有被释放掉,内存泄露.
(2)a和b的指针指向相同的字符串,当其中一个离开生存空间,其destructor会删除内存,另外一个悬垂指针.
如:
#include<iostream>
using namespace std;
class String
{
public:
String(const char* value);
~String();
friend ostream& operator << (ostream& out, const String str);
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';
}
}
String::~String()
{
delete[] data;
}
ostream& operator << (ostream& out, const String str)
{
return out << str.data;
}
int main()
{
String a("Hello");
{
String b("Word");
b = a;
}
String c=a;
//这里c.data如今没有定义.
cout << c << endl;
return 0;
}
特别注意:String c=a;
这句话调用copy constructor.导致a和c指向同一个地方,这样那个地方会被删除两次.
2,只要程序中有pass-by-value的动作,就会调用copy constructor.
void doNothing(String localString) {}
String s = "The Truth Is Out There";
doNothing(s);
这里s会产生一个副本,函数调用完成后,副本释放,导致s内含指针被删除.
而当s离开作用域,又会对相同的地方再次删除,其行为未定义.
3,解决之道:
(1)如果class拥有任何指针,那么撰写自己的copy constructor和assignment operator.
将指针所指数据结构复制,保证每个对象拥有属于自己的一份拷贝,或者实现某种引用计数策略.
(2)如果你的class不会执行copy或assignment动作,那么将其声明为private,并且不要定义.
4,自己给出的代码:
#include <iostream>
#include <string.h>
using namespace std;
class String
{
public:
String(const char* value);
String(const String& rhs);
~String();
String& operator=(const String& rhs);
friend ostream& operator << (ostream& out, const String str);
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';
}
}
String::String(const String& rhs)
{
data = new char[strlen(rhs.data)+1];
strcpy(data, rhs.data);
}
String::~String()
{
delete[] data;
}
String& String::operator=(const String& rhs)
{
if (this == &rhs)
return *this;
delete[] data;
data = new char[strlen(rhs.data)+1];
strcpy(data, rhs.data);
return *this;
}
ostream& operator << (ostream& out, const String str)
{
return out << str.data;
}
int main()
{
String a("Hello");
cout << a << endl;
{
String b(a);
cout << b << endl;
}
String c = a;
cout << c << endl;
return 0;
}