首页 > 代码库 > 智能指针

智能指针

  • RAII(Resource Acquisition Is Initialization)

资源分配即初始化,定义一个类来封装资源的分配和释放,在构造函数完成资源的分配和初始化,在析构函数完成资源的清理,可以保证资源的正确初始化和释放。


-------------------------------------------------------------------------------------------


为什么要有智能指针呢?

    智能指针的存在是为了防止我们在大型项目中忘记释放空间而导致很恐怖的空间浪费,通过RAII,实现智能指针的类实现,而完成指针的自动释放。

STL--auto_ptr

Boost库的智能指针(ps:新的C++11标准中已经引入了unique_ptr/shared_ptr/weak_ptr)

技术分享技术分享


auto_ptr:这个指针是现在是不提倡使用的,理由如下:

     auto_ptr对象被拷贝或者被赋值后,已经失去了对原指针的所有权,此时,对这个auto_ptr的读取操作是不安全的。出现在将auto_ptr作为函数参数按值传递,因为在函数调用过程中在函数的作用域中会产生一个局部的临时auto_ptr对象来接收传入的 auto_ptr(拷贝构造),这样,传入的实参auto_ptr的对其指针的所有权转移到了临时auto_ptr对象上,临时auto_ptr在函数退出时析构,所以当函数调用结束,原实参所指向的对象已经被删除了。


scoped_ptr:就是防拷贝的RAII智能指针实现。

shared_ptr:就是存在引用计数,浅拷贝的智能指针实现

weak_ptr:就是解决当shared_ptr出现循环引用时解决而出现的弱指针。


-------------------------------------------------------------------------------------------------------------------

循环引用问题:

技术分享


强引用和弱引用

一个强引用当被引用的对象活着的话,这个引用也存在(就是说,当至少有一个强引用,那么这个对象就不能被释放)。boost::share_ptr就是强引用。

相对而言,弱引用当引用的对象活着的时候不一定存在。仅仅是当它存在的时候的一个引用。弱引用并不修改该对象的引用计数,这意味这弱引用它并不对对象的内存进行管理,在功能上类似于普通指针,然而一个比较大的区别是,弱引用能检测到所管理的对象是否已经被释放,从而避免访问非法内存。

----------------------------------------------------------------------------------------------------------------------------


下面是简单的代码实现:

#pragma once
#include <assert.h>

// RAII

template<class T>
class AutoPtr
{
public:
	explicit AutoPtr(T* ptr)
		:_ptr(ptr)
	{}

	~AutoPtr()
	{
		if (_ptr)
		{
			delete _ptr;
			_ptr = NULL;
		}
	}

	AutoPtr(AutoPtr<T>& ap)
		:_ptr(ap._ptr)
	{
		ap._ptr = NULL;
	}

	AutoPtr& operator=(AutoPtr<T>& ap)
	{
		if(&ap != this)
		{
			if (_ptr && _ptr != ap._ptr)
			{
				delete _ptr;
			}

			_ptr = ap._ptr;
			ap._ptr = NULL;
		}

		return *this;
	}

	T& operator*()
	{
		assert(_ptr);
		return *_ptr;
	}

	T* operator->()
	{
		return _ptr;
	}

	T* GetPtr()
	{
		return _ptr;
	}

	bool operator==(const AutoPtr<T>& ap)
	{
		return _ptr == ap._ptr;
	}

protected:
	T* _ptr;
};

// C++98/03
// 
void Test1()
{
	AutoPtr<int> ap1(new int(1));
	//AutoPtr<int> ap1 = new int(1);

	AutoPtr<int> ap2(ap1);

	cout<<*ap1<<endl;

	AutoPtr<int> ap3(new int(2));
	ap3 = ap1;
}

// Boost
template<class T>
class ScopedPtr
{
public:
	ScopedPtr(T* ptr)
		:_ptr(ptr)
	{}

	~ScopedPtr()
	{
		if (_ptr)
		{
			delete _ptr;
			_ptr = NULL;
		}
	}

	T& operator*()
	{
		//assert(_ptr);
		return *_ptr;
	}

	T* operator->()
	{
		return _ptr;
	}

	T* GetPtr()
	{
		return _ptr;
	}

	// 只声明不实现
private:
	ScopedPtr(const ScopedPtr<T>& ap);
	ScopedPtr& operator=(const ScopedPtr<T>& ap);

protected:
	T* _ptr;
};

void Test2()
{
	ScopedPtr<int> ap1 = new int(1);
	//ScopedPtr<int> ap2(ap1);
}

// 引用计数->
template<class T>
class SharedPtr
{
public:
	SharedPtr(T* ptr)
		:_ptr(ptr)
		,_count(new int(1))
	{}

	SharedPtr(SharedPtr<T>& sp)
		:_ptr(sp._ptr)
		,_count(sp._count)
	{
		//++_count[0];
		++(*_count);
	}

	SharedPtr& operator=(const SharedPtr<T>& sp)
	{
		//if (this != &sp)
		if (_ptr != sp._ptr)
		{
			_Release();

			_ptr = sp._ptr;
			_count = sp._count;
			++(*_count);
		}

		return *this;
	}

	void _Release()
	{
		if (--(*_count) == 0)
		{
			cout<<"Delete"<<endl;
			delete _count;
			delete _ptr;
		}
	}

	~SharedPtr()
	{
		_Release();
	}

private:
	T* _ptr;
	int* _count;
};

struct AA
{
	AA()
	{
		cout<<"AA()"<<endl;
	}

	~AA()
	{
		cout<<"~AA()"<<endl;
	}

	int a;
};

//template<class T>
//class SharedArray
//{
//public:
//	//operator-> X
//	//operator*  X
//	T& operator [](size_t index)
//	{
//		return _ptr[index];
//	}
//
//	~SharedArray()
//	{
//		if (--(*_count) == 0)
//		{
//			delete[] _ptr;
//			delete _count;
//		}
//	}
//private:
//	T* _ptr;
//	int* _count;
//};

void Test3()
{
	SharedPtr<AA> sp1(new AA[10]);
	SharedPtr<AA> sp2(sp1);

	SharedPtr<int> sp3(new int);
	//SharedPtr<int> sp4(sp3);

	//sp2 = sp3;
}


以上。


本文出自 “剩蛋君” 博客,转载请与作者联系!

智能指针