C++基础之创建自己的智能指针

本文介绍了C++中创建自定义智能指针以防止内存泄漏的方法,通过构造函数和析构函数确保内存管理。文章探讨了运算符重载、拷贝构造函数和赋值运算符的重要性,并提出了引用计数的智能指针策略,讨论了引用计数在多对象共享内存时的作用,同时提到了`boost::shared_ptr`作为C++中的一种实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    在C++中,忘记释放指针指向的内存,是造成内存泄露的一个主要原因。如果我们能保证,对每一个int* p = new int; 能有一个 delete p; 匹配,就能很好的管理内存。构造函数和析构函数是成对出现的好伙伴,把指针操作包装成一个类。重载运算符*,这样在语法上可以像使用普通指针一样使用My_IntPtr。

class My_IntPtr
{
public:
	My_IntPtr(int* p)
	{
		m_p = p;
	}

	~My_IntPtr()
	{
		delete m_p;
	}

	int& operator*()
	{
		return *m_p;
	}
private:
	int* m_p;
};

 

通过My_IntPtr来使用指针,不会担心内存泄露的问题。

	int* p = new int;
	My_IntPtr pi(p);
	*(pi.m_p) = 10; //访问成员变量方法(成员变量要public的才行)

	*pi = 18; //利用了重载的*运算符


P.S. 运算符重载:只是一种语法上的方便,本质上它就是函数调用,函数的名字是operator@,其中@是被重载的运算符。

返回值int&,而不是int。如果返回int型的话,相当于是个常量,不能作为左值(可以改变值的变量)被赋值了,这与平常的习惯不符。

以下三种情况,编译器报错:left operand must be l-value

	*pi = 18; //利用了重载的*运算符,且返回int
	
	const int num = 5;
	num = 9;

	int a[3];
	a++;

 

返回 int& 的值:

	My_IntPtr pi(new int);
	*pi = 18; //重载*,返回int&
	int& i = *pi;
	i = 19;
	cout << *pi << endl; //Output: 19


如果类里面有指针指向动态分配的内存,那么要为这个类添加一个拷贝构造函数和赋值运算符,不然按照默认的浅拷贝,一旦做了赋值,两个对象的指针会指向同一块内存,析构的时候会出错。

可见 pi和pi_2的地址是一样的,指向同一块内存。



析构时,在C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\dbgdel.cpp 的delete() 中报错。

 

深拷贝不适合,如果智能指针指向一个复杂的对象呢,如果这个对象有一个私有的拷贝构造函数不能拷贝呢。

当当当,我们采用引用计数的方法来实现智能指针。为每个指针维护一个引用计数值,每次拷贝构造或者赋值,计数+1,因为指向该内存块的指针多了一个;每当指针销毁,计数值-1,当计数值=0时,没有指针指向该内存块,可以安全的释放了。

class My_IntPtr
{
public:
	My_IntPtr(int* p)
	{
		m_p = p;
		m_count = new int;
		*m_count = 1; //初始化计数为1
	}

	//拷贝构造函数
	My_IntPtr(const My_IntPtr& rhs)
	{
		m_p = rhs.m_p; //指向同一块内存
		m_count = rhs.m_count; //使用同一个计数值
		(*m_count)++; //计数值加1
	}

	~My_IntPtr()
	{
		(*m_count)--;
		if (m_count == 0) //计数值为0,释放内存
		{
			delete m_p;
			delete m_count;
		}
	}

	//赋值运算符
	My_IntPtr& operator=(const My_IntPtr& rhs)
	{
		if (m_p == rhs.m_p) //首先判断是否本来就指向同一块内存
			return *this;

		(*m_count)--; //计数值减1,因为该指针已经不指向原来的内存块了
		if (m_count == 0) //计数值为0,释放内存
		{
			delete m_p;
			delete m_count;
		}

		m_p = rhs.m_p;
		m_count = rhs.m_count;
		(*m_count)++;
	}

	int& operator*()
	{
		return *m_p;
	}

private:
	int* m_p;
	int* m_count;
};

注意赋值运算符里的处理,要先释放原来指向的内存,再指向新的内存。

这是一个用C++实现的简单的垃圾收集机制。

目前C++中有一个引用计数的智能指针,boost::shared_ptr。下一篇文章来讨论。

 【参考】

Solmyr 的小品文系列之五:垃圾收集

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值