类的动态内存分配 和复制构造函数

class class_base
{
	int* pt;
public:
	class_base(int);//构造函数
	class_base(const class_base&);//复制构造函数
	virtual void show_info();
	virtual ~class_base();//析构函数
};

举例所用的类class_base如上面所示,具体的定义下面会给出。如果类的数据成员中使用了动态内存分配(如上面的int* pt;),则必须要显式的定义复制构造函数,重载赋值运算符,和析构函数。原因很简单,首先来说构造函数。如果不显式的定义复制构造函数而是使用默认的版本,则只会简单的复制类的数据成员,包括指针。如果执行下述代码

int main()
{
	class_base *pt_1;
	pt_1 = new class_base(1);
	class_base *pt_2;
	pt_2 = new class_base(*pt_1);
}

类对象*pt_1和*pt_2的数据成员pt_1->pt,pt_1->pt是完全相同的,即指针地址相同,或者说两个指针指向了同一片内存。如果类对象*pt_1的生命周期结束,则其析构函数会被调用,指针pt指向的内存也随之被释放(这里也是为何需要显式定义析构函数的原因,如果不显式定义,只是简单释放所有数据成员,即把指针pt的值清理了,但pt所指向的内存却依然存在,并且,随着指针的被清理,内存变成了无法访问无法寻找的内存。因此,在析构函数中必须使用delete关键字把动态分配的内存释放掉)。等一下,pt_2的生命周期没有结束,但pt_2->pt指向的内存却被释放了? 显然这是矛盾的,因此我们需要显式的定义复制构造函数。代码如下
class_base::class_base(int vl)
{
	pt = new int(vl);
}
class_base::class_base(const class_base& cb)//显示
{
	pt = new int(*(cb.pt));
}
void class_base::show_info()
{
	cout << *pt << endl;
}
class_base::~class_base()
{
	delete pt;
}
显然,在调用复制构造函数的时候,为新生成的对象的数据成员动态分配了新的内存,然后把这块内存设置成与被复制对象相同的值或者状态。下面调用代码进行测试。

int main()
{
	class_base *pt_1;
	pt_1 = new class_base(1);
	class_base *pt_2;
	pt_2 = new class_base(*pt_1);
	pt_1->show_info();
	pt_2->show_info();
	delete pt_1;
	pt_2->show_info();
	system("pause");
	delete pt_2;
	return 0;
}
可以正常输出,结果如下图所示


如果此时我们对类方法的进行修改,去掉显式的复制构造函数,而是使用默认版本的,结果如下


为什么会出现这个结果呢,原因很简单,像上面所说的,两个对象*pt_1,*pt_2的成员完全相同,其中一个被delete了,则另一个的成员指针指向的内存被释放掉了,你再用这个指针去访问一片被delete的内存,显然得不到你想得到的东西~

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值