Effective C++ 学习笔记11

条款11:为需要动态分配内存的类(含有指针的类)声明一个拷贝构造函数呃一个赋值操作符


请注意下面这段代码:

#include <iostream>

class String
{
public:
	String(const char* value)
	{
		if (value)
		{
			int length = strlen(value) + 1;
			data = new char[length];
			memcpy(data, value, length);
		}
		else
		{
			data = new char[1];
			data[0] = '\0';
		}
	}
	~String()
	{
		if (data)
		{
			delete[] data;
		}
	}
private:
	char* data;
};
int main()
{
	String a("Hello");
	String b("World!");

	b = a;  //默认operator=

	return 0;
}
以上这段代码会产生如下问题:

  1.b.data和a.data指向了同一块内存,由于程序结束时,对象a和对象b都会调用各自的析构函数,导致一块相同的内存被释放了两次;

  2.对象b.data指向的内存不会被删除,产生了内存泄露(注:程序关闭时,内存会被系统回收)。

  之所以产生上述问题,是因为调用了默认的operator=,该操作是对类的数据成员进行逐位拷贝(为了兼容C语言的struct),所以对指针来说,得到的是地址,而并非里面的内容。

  默认的拷贝构造函数和默认的赋值运算符几乎会产生一样的问题。

  请看下面一个关于默认的拷贝构造函数的例子:

void doNothing(String localString) {}
String s = "The Truth Is Out There";
doNothing(s);

  当s作为实参传递到函数中时,调用的是默认的拷贝构造函数,当形参离开他的生存空间,就会释放s所占用的内存,然后s在离开它自己的生存空间时,就会报错,因为对象s的析构函数去delete一个已经delete的指针。

  所以,为了避免此类情况,只要类里面有指针,我们就要写自己版本的拷贝构造函数和赋值运算符函数。

  有时候,我们要禁止类的赋值运算,我们可以把自定义的operator=函数声明为私有函数,并且不去定义它,这样一来,程序只要一有该类的赋值运算,编译器就会有反应(注:如果你去实现了该函数,则该类的成员函数和类的友元一样可能会使用该函数)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值