内存泄漏与智能指针

对于c++这种没有垃圾回收机制的语言来说,主要关注两种类型的内存泄漏;

(1) 堆内存泄漏:比如使用new、malloc等从堆中分配的资源,没有用delete和free删掉

(2) 系统资源泄漏:系统分配的资源如socket等没有被释放掉。

    智能指针是一个类, 这个类的构造函数会传入一个普通指针,析构函数中释放传入的指针。智能指针都是栈上的对象,所以当函数(或程序)结束时会自动会被释放。

引用型智能指针的实现:

template<typename T>
class SmartPointer
{
public:
	//构造函数
	SmartPointer(T* p = 0) : ptr(p), reference_count(new size_t)
	{
		if (p)
		{
			*reference_count = 1;
		}
		else
		{
			*reference_count = 0;
		}
	}
	//拷贝构造函数
	SmartPointer(const SmartPointer& other)
	{
		if (this != other)
		{
			ptr = other.ptr;
			reference_count = other.reference_count;
			reference_count++;
		}
	}
	//operator= 重载
	SmartPointer& operator=(const SmartPointer& other)
	{
		if (ptr == other.ptr)
			return *this;
		releaseCount();
		ptr = other.ptr;
		reference_count = other.reference_count;
		(*reference_count)++;
		return *this;
	}
	
	//重载操作符
	T& operator*()
	{
		if (ptr)
			return *ptr;
	}
	T* operator->()
	{
		if (ptr)
			return ptr;
	}
	~SmartPointer()
	{
		if (--(*reference_count) == 0)
		{
			delete ptr;
			delete reference_count;
		}

	}
	
private:
	size_t *reference_count;
	T *ptr;
	void releaseCount()
	{
		if (ptr)
		{
			(*reference_count)--;
			if (*reference_count == 0)
			{
				delete reference_count;
				delete ptr;
			}
		}
	}
};

     shared_ptr多个指针指向相同的对象。shared_ptr使用引用计数,每一个shared_ptr的拷贝都指向相同的内存。每使用一次,内部的引用计数加1,每析构一次,内部的引用计数减1,减为0的时候,自动删除所指向的堆内存。shared_ptr内部的引用计数是线程安全的,但是对象的读取需要加锁。

     注意事项:不要用一个原始指针初始化多个shared_ptr; 不要在函数实参中创建shared_ptr,在调用函数之前先定义以及初始化它; 不要讲this指针作为shared_ptr返回出来; 要避免循环引用。

    unique_ptr是独占的智能指针

    unique_ptr是一个独占的智能指针,它不允许其他的智能指针共享其内部的指针,不允许通过赋值将一个unique_ptr赋值给另外一个unique_ptr. unique_ptr不允许赋值,但是可以通过函数返回给其他的unique_ptr,还可以通过std::move来转移到其它的unique_ptr, 这样它本身就不再拥有原来的指针的所有权了。如果希望只有一个只能指针管理或管理数组就用unique_ptr,如果希望多个智能指针管理同一个资源就用shared_ptr。

weak_ptr弱引用的智能指针:

   弱引用的智能指针weak_ptr是用来监视shared_ptr的,不会使引用计数加1,它不管理shared_ptr内部的指针,主要是为了监视shared_ptr的生命周期。weak_ptr没有重载运算符*和->, 因此它不会共享指针,不能操作资源,主要是为了通过shared_ptr获得资源的监测权,它的构造不会增加引用计数,它的析构不会减少引用计数。weak_ptr还可以用来返回this指针和解决循环引用的问题。

循环计数问题:

#include <iostream>
#include <memory>

using namespace std;

class B;
class A
{
public:
	shared_ptr<B> pb;
	~A() { cout << "destruct A" << endl; }
	A() { cout << "constrct A" << endl; }
};

class B
{
public:
	shared_ptr<A> pa;
	~B() { cout << "destruct B" << endl; }
	B() { cout << "construct B" << endl; }
};

int main()
{
	shared_ptr<A> spa = make_shared<A>();
	shared_ptr<B> spb = make_shared<B>();
	spa->pb = spb;
	spb->pa = spa;
	cout << "spa use_count" << spa.use_count() << "   spb use_count"
		<< spb.use_count() << endl;
	return 0;
}

 

解决办法:

#include <iostream>
#include <memory>

using namespace std;

class B;
class A
{
public:
	weak_ptr<B> pb;
	~A() { cout << "destruct A" << endl; }
	A() { cout << "constrct A" << endl; }
};

class B
{
public:
	weak_ptr<A> pa;
	~B() { cout << "destruct B" << endl; }
	B() { cout << "construct B" << endl; }
};

int main()
{
	shared_ptr<A> spa = make_shared<A>();
	shared_ptr<B> spb = make_shared<B>();
	spa->pb = spb;
	spb->pa = spa;
	cout << "spa use_count" << spa.use_count() << "   spb use_count"
		<< spb.use_count() << endl;
	return 0;
}

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值