【条款5】know what functions C++ silently writes and calls

如果没有为一个类声明construct function、copy construct function、copy assignment function、destruct function,编译器就会为之声明默认版本。

class Empty{
public:
	Empty() {...}
	Empty(const Empty &ths) {...}
	~Empty() {...}

	Empty& operator= (const Empty &rhs) {...}
};

注意:1、这些默认版本的函数都是public and inline;

    2、只有当这些函数被调用时,才会被编译器创建出来。

然而,在某些情况下,需要自己实现这些函数,否则无法实现程序的本意。这就是C++中最容易出问题的地方,也恰恰是其迷人之处。这些情况包括:

1、涉及到资源分配;

2、涉及到const成员、引用等。

在《C++ Primer》中,第13章“复制控制”专门讲解了相关的内容。

所谓的资源分配就是指类的数据成员中有指针类型,这时候就需要进行深拷贝,而默认版本的copy construct 只能完整深拷贝。这时候就需要自己编写“复制控制”的相关函数。

对于const 数据成员,由于const属性,该成员不可以被更改,所以default copy construct是非法的;而引用,同样也不可以让其改指不同的对象。

如果有以上情况出现,而有没有自己定义复制控制,编译器就会拒绝编译。

还有一种情况编译器也会拒绝编译:基类将copy assignment操作符声明为private,编译器将拒绝为其派生类生成一个copy assignment操作符

一个小例子:

//myheader.h

#ifndef __MYHEADER_H
#define __MYHEADER_H

class A{
public:
	A(int n);
	A();
	~A();

//	A& operator= (const A &a);
private:
	int **data;
	int size;
};


#endif

//myheader.cpp

#include "myheader.h"
#include <stdio.h>
A::A(): data(NULL),size(0)
{}

A::A(int n)
{
	size = n;
	data = new int*[n];
	for(int i=0; i<n; i++)
		data[i] = NULL;
}

A::~A()
{
	if(data)
		for(int i=0; i<size; i++)
			delete []data[i];
}

//test.cpp

int main()
{
	A *a = new A[3];

	A b(2);
	
	for(int i=0; i<3; i++)
	{
		A c(2);
		a[i] = c;
	}
	
	return 0;

}
这个小例子中,没有声明自己的copying assignment函数,所以系统会默认提供一个,但是本例中又涉及到了资源分配,而默认copying assignment只能无法实现深拷贝,这样程序就会出现问题。

在test.cpp文件中的for循环是为了将数组a初始化,可能达到目的吗?答案是否定的。在循环中,声明了一个对象c,然后用对象c初始化a[i],这时候a[i]的数据成员指针和c的数据 成员指针指向的是同一块内存区域。初始化完毕后,问题马上就出现了:由于c在块作用域里,其声明周期在一次循环后就结束,所以每次循环后,都会调用析构函数,释放动态分配的内存,这也意味着a[i]的数据成员指针指向的内存区域也被释放掉了!!!这显然是错误的!

挽救方案就是定义自己的copying assignment函数,实现深拷贝。

A& A::operator= (const A &a)
{
	if(data != NULL){
		for(int i=0; i<size; i++){
			delete []data[i];
			data[i] = NULL;
		}
	}
	
	/**data = NULL;*/

	size = a.size;
	data = new int*[size];
	for(int i=0; i<size; i++){
		data[i] = NULL;
	}
	
	return *this;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值