1. 程式人生 > >C++探索智慧指標

C++探索智慧指標

一、 RAII(Resource Acquisition Is  Initialization)

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

RAII是一種思想,智慧指標是RAII思想的一種應用。

小知識:別的語言都有gc垃圾回收,即在堆上建立的記憶體,在不用這個物件時,會自動回收這些空間,使用智慧指標也可以達到這樣的效果。

智慧指標的定義:

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

	}
	~AutoPtr()
	{
		printf("_ptr:%p\n", _ptr);//檢測是否析構
		delete _ptr;
	}
private:
	T *_ptr;
};

我們知道,一般程式下,若出現異常,程式回終端,則不回走到delete,就造成了記憶體洩漏。若用智慧指標,將建立的指標的地址傳入智慧指標,出了類的作用域,物件會自動析構,所以開闢的空間也會析構。不管會不會遇到異常,還可以解決忘記delete的諸多問題,減輕了程式設計師的負擔。

#include"smartPstr.hpp"

void DoSomeThing()
{
	throw string("拋異常");
}
void testSm()
{

	AutoPtr<int> ap1(new int(2));

	DoSomeThing();
}
int main()
{
	try
	{
		testSm();
	}
	catch (string s)
	{
		cout << s << endl;
	}

	return 0;
}

所以智慧指標有兩個特性:1、滿足RAII思想 2、像一個指標 3、深淺拷貝   

所以現在的問題是指標有何特性,若何時智慧指標更像一個指標。

解決深淺拷貝

1、auto_ptr

  管理權轉移的辦法

但是管理權轉移是有缺陷的設計,一般不清楚內部設計的會認為被轉移許可權的指標還存在,容易導致空指標的問題出現,所以很多公司的內部文件明確規定不要使用auto_ptr.

2、Scoped_ptr:  它的設計理念就是防拷貝,簡單粗暴。

 將拷貝構造和賦值運算子過載定義為私有且不實現,就可做到防拷貝。

3、SharedPtr 共享指標: 引用計數

template<class T>
class SharedPtr
{
public:
	SharedPtr(T * pty)
		:_ptr(pty)
		, _pcount(new int(1))
	{

	}

	SharedPtr(const SharedPtr<T>& sp)
	{
		_ptr = sp._ptr;
		_pcount = sp._pcount;
		(*(_pcount))++;
	}
	~SharedPtr()
	{
		if (--(*_pcount) == 0)
		{
			printf("_ptr:%p\n", _ptr);
			delete _ptr;
			delete _pcount;
		}
	}

	SharedPtr<T>& operator=(SharedPtr<T>& sp)
	{
		if (this != &sp)
		{
			if (--(*_pcount) == 0)
			{
				delete _ptr;
				delete _pcount;
			}
			_ptr = sp._ptr;
			_pcount = sp._pcount;
			(*_pcount)++;
		}
		return *this;
	}

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

	T* operator->()
	{
		return _ptr;
	}
protected:
	T * _ptr;
	int* _pcount;
};

4、weakPtr  解決迴圈引用  weak_ptr是為配合shared_ptr而引入的一種智慧指標來協助shared_ptr工作,它可以從一個shared_ptr或另一個weak_ptr物件構造,它的構造和析構不會引起引用記數的增加或減少。沒有過載*和->但可以使用lock獲得一個可用的shared_ptr物件

 

二、探索shared_ptr

上一部分實現的簡化版sharedptr看起來不錯,起始還有存在以下問題;

1、引用計數更新存線上程安全問題

2、迴圈引用問題;

3、定置刪除器;

知識點:仿函式----函式物件   一個類過載(),可以用這個物件來實現傳參