智能指針

  • RAII(Resource Acquisition Is Initialization)

資源分配即初始化,定義一個類來封裝資源的分配和釋放,在構造函數完成資源的分配和初始化,在析構函數完成資源的清理,可以保證資源的正確初始化和釋放。


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


爲什麼要有智能指針呢?

    智能指針的存在是爲了防止我們在大型項目中忘記釋放空間而導致很恐怖的空間浪費,通過RAII,實現智能指針的類實現,而完成指針的自動釋放。

STL--auto_ptr

Boost庫的智能指針(ps:新的C++11標準中已經引入了unique_ptr/shared_ptr/weak_ptr)

spacer.gifwKioL1fAFcuArHC3AABUbtQsqXU175.png


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出現循環引用時解決而出現的弱指針。


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

循環引用問題:

wKiom1fAF1aBRrmKAAAeDSceYxM125.png


強引用和弱引用

一個強引用當被引用的對象活着的話,這個引用也存在(就是說,當至少有一個強引用,那麼這個對象就不能被釋放)。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;
}


以上。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章