通过实例分析C++中的析构函数

实例源代码heap_data_member.cpp

/*************************************
  Critter Farm
  version: 1.0
  -------------------------
  Heap Data Member
  Demonstrates an object with a dynamically allocated data member
  //destructor prototype
  //copy constructor prototype
  //overloaded assignment op

  version: 2.0
  date: 2014/07/07 16:40
**************************************/

#include <iostream>
#include <string>  
using namespace std;

class Critter
{
public:
	Critter(const string& name="", int age = 0);
	~Critter();		//destructor prototype
	Critter(const Critter& c);		//copy constructor prototype
	Critter& Critter::operator=(const Critter& c);		//overloaded assignment op

	void Greet() const;

	/* data */
private:
	string* m_pName;
	int m_Age;
};

Critter::Critter(const string& name, int age)
{
	cout << "constructor called." << endl;
	m_pName = new string(name);
	m_Age = age;
}

Critter::~Critter()
{
	cout << "Destructor called." << endl;
	delete m_pName;
}

Critter::Critter(const Critter& c)
{
	cout << "Copy constructor called." << endl;
	m_pName = new string(*(c.m_pName));
	m_Age = c.m_Age;
}

Critter& Critter::operator=(const Critter& c)
{
	cout << "Overloaded assignment operator called." << endl;
	if (this != &c)
	{
		delete m_pName;
		m_pName = new string(*(c.m_pName));
		m_Age = c.m_Age;
	}
	return *this;
}

void Critter::Greet() const
{
	cout << "I'm " << *m_pName << " and I'm " << m_Age << " years old." << endl;
	cout << "&m_pName: " << &m_pName << endl;
}

void testDestructor();
void testCopyConstructor(Critter aCopy);
void testAssignmentOp();

int main(int argc, char const *argv[])
{
	testDestructor();
	cout << endl;

	Critter crit("Poochie", 5);
	crit.Greet();
	testCopyConstructor(crit);
	crit.Greet();
	cout << endl;

	testAssignmentOp();

	return 0;
}

void testDestructor()
{
	Critter toDestroy("Rover", 3);	//创建对象在栈中分配内存
	toDestroy.Greet();
}

void testCopyConstructor(Critter aCopy)
{
	aCopy.Greet();
}

void testAssignmentOp()
{
	Critter crit1("crit1", 7);
	Critter crit2("crit2", 9);
	crit1 = crit2;

	crit1.Greet();
	crit2.Greet();
	cout << endl;

	Critter crit3("crit3", 11);
	crit3 = crit3;
	crit3.Greet();
}


声明与定义析构函数
当对象的数据成员指向堆中的值时,可能产生的问题就是内存泄露。这是因为当对象被删除时,指向堆中值的指针也随之消失。如果堆中的值还存在,那么将造成内存泄露。如果要避免内存泄露,对象应当在销毁之前做好清理工作,删除与之相关的堆中值。幸运的是,有一种称为析构函数的成员函数,它恰好会在对象销毁之前被调用,以便用于执行必要的清理工作。
如果不编写自己的析构函数,则编译器体程序员创建一个默认析构函数,但它并不尝试释放掉任何数据成员可能指向的堆中的内存。对于简单的类而言,这样做通常是没有问题。但是当类中有数据成员指向堆中值时,则应当编写自己的析构函数,以便能在对象消失之前释放与对象相关的堆中内存,避免内存泄露。
Critter::~Critter()
{
    cout << "Destructor called." << endl;
    delete m_pName;
}
testDestructor()测试了该析构函数。该函数终止时,toDestroy对象即将被销毁。
幸运的是,toDestroy恰好在销毁之前调用其析构函数。析构函数显示Destructor called.
然后删除堆中等于“Rover”的string对象,完成清理工作,并且没有泄露内存。析构函数没有对m_Age数据成员做任何处理。这完全没有问题,因为m_Age是toDestroy的一部分,分配在栈中,会由系统对Critter对象妥善处理。
提示 :如果类在堆中分配内存,则应当编写析构函数来清理与释放堆中的内存。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值