条款11:如果class内动态配置有内存,请为此class声明一个copy constructor和一个assignment运算符...

本文探讨了C++中自定义字符串类的深拷贝问题,包括如何正确实现拷贝构造函数和赋值操作符以避免内存泄漏和其他潜在问题,并提供了一个完整的示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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会删除内存,另外一个悬垂指针.
如:

#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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值