智能指针

1. 什么是智能指针?

智能指针是存储指向动态内存分配的,在类的构造是传入一个指针,在析构是释放指针。智能指针面对异常时格外有用,它们能够正确的销毁动分配的对象,

2.为什么要使用智能指针?

我们会经常遇到一下问题:

void fun(int *p)
{
	*p = 5;
	cout << *p << endl;
	delete p;
}

int main()
{
	int *q = new int;
	fun(q);
	cout << *q << endl;

	return 0;
}

上面的代码出现的问题是:main函数申请了一片空间,但是在掉fun函数是把申请的空间释放了,这就导致main函数在后面打印*q时出错。

继续看下面的问题:

int main()
{
	int *p = new int;

	delete p;
	return 0;
}

从代码角度看出main函数申请了一片内存,在后面也delete p将内存释放了,但是p指向的这片空间任然可以使用,这就是所谓的空悬指针(野指针),它会指向垃圾内存,给程序造成隐患。必须在后面将p置为NULL;

 

<1>. 智能指针可以帮助我们处理内存泄漏问题

<2>.智能指针可以帮助我们处理野指针的问题

<3>.智能指针可以帮我们处理比较隐晦的由异常造成的资源泄漏

事实上,智能指针还可以处理很多事情,例入处理线程安全,提供写时拷贝,确保协议等等。只能指针大部分用于生存期的控制,阶段控制。

3. 按照谁申请谁释放这一原则看以来完全欧克,但是当一个内存被多个函数使用是该由谁来是释放?

常见的只能指针:

<1>. shared_ptr强智能指针:基于引用计数的智能指针,它可以自由的共享它所指向的对象,可以随意赋值,直到这片内存的引用计数为0的时候才会被释放,也就是说在最后的一个对象销毁所有的资源内存。

<2>.weak_ptr弱智能指针:引用计数有一个问题,交叉引用形成环,使两个指针指向的内存都无法得到释放。需要手动打破循环引用或者使用弱指针weak_ptr。weak_ptr弱引用,只引用不计数。一片内存sheard_ptr和weak_ptr同时被引用,当所有sheard_ptr析构释放之后,不管有没有weak_ptr引用该内存,内存也会被释放。所以weak_ptr所指向的内存不能保证一定是有效的,在使用之前需要检查weak_ptr是否是空指针。

shared_ptr智能指针的实现


template <typename	T>

class smartPtr

{

private:

	T* _ptr;

	static map<T*, int> _num;

public:

	smartPtr(T *p)//构造函数

	{

		_ptr = p;

		if (_num.find(p) != _num.end())

		{

			_num[p]++;

		}

		else

		{

			_num.insert(make_pair(p, 1));

		}

		cout << _ptr << ";" << _num[_ptr] << endl;

	}

	smartPtr(const smartPtr& src)//拷贝构造

	{

		_ptr = src._ptr;

		_num[src._ptr]++;

	}

	~smartPtr()//析构函数

	{

		cout << "~smartPtr()" << endl;

		if (--_num[_ptr] == 0)

		{

			delete _ptr;

		}

		cout << _ptr << ";" << _num[_ptr] << endl;

	}

	T& operator*()//重载运算符*

	{

		return *_ptr;

	}

	T* operator->()//重载运算符->

	{

		return _ptr;

	}

};

template<typename T>

map<T*, int> smartPtr<T>::_num = map<T*, int>();

拷贝构造时,先找一下p这个指针有没有指向一片内存,如果有那么这片内存的引用计数+1,如果没有,则给p一片内存,这片内存的引用计数置为1。在析构的时候判断一下要析构的指针指向的内存的引用计数是否为0,若为0,则不释放,直到这片内存的引用计数为0才释放这片内存。

交叉引用及解决办法:


class B;

class A

{

public:

 

    A()

    {

        cout << "A()" <<endl;

    }       

    ~A()

    {

        cout << "~A()" <<endl;

    }

    Shared_ptr<B> _ptrb;

};

 

class B

{

 public:

    B()

    {

        cout << "B()" <<endl;

    }       

    ~B()

    {

        cout << "~B()" <<endl;

    }

    Shared_ptr<A> _ptra;

 

};

int main()

{

    shared_ptr<A> ptra(new A());

    shared_ptr<B> ptrb(new B());

 

    ptra->ptrb = ptrb;

    ptrb->ptra = ptra;

 

    return 0;

}

在这段代码中A类中有指向B类的shared_ptr指针,B类中也有指向A类的shared_ptr指针,A和B中的计数引用都为2,当main函数返回后,A和B的计数引用都变为1,所以内存不能释放,程序结束造成内存泄漏。

解决的办法:

在A和B类中使用sheard_ptr智能指针的地方全部换成weak_ptr智能指针。在使用强弱智能指针的时候有一个原则,就是只有在创建它的对象的时候才使用强智能指针,在其他地方想使用对象的时候都用弱智能指针。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值