您的位置:首页 > 编程语言 > C语言/C++

Effective C++ 学习笔记11

2015-02-16 17:07 309 查看
条款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=函数声明为私有函数,并且不去定义它,这样一来,程序只要一有该类的赋值运算,编译器就会有反应(注:如果你去实现了该函数,则该类的成员函数和类的友元一样可能会使用该函数)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: