智能指針

目錄

1、智能指針

2、shared_ptr

3、weak_ptr

4、unique_ptr


1、智能指針

在C++中,內存管理是用new和delete來實現的。

1)new:爲對象分配一塊內存空間;

2)delete:釋放new開闢的空間。

內存使用中經常會出現兩種問題:

1)一塊在使用的內存,被釋放掉;

2)不再使用的內存未被釋放;

爲解決這兩個問題引入了智能指針的概念:它會自動釋放不再使用的內存未被釋放。

2、shared_ptr

1)概念

shared_ptr<>實現多個智能指針可以指向同一個對象,該對象和其相關資源會在最後一個引用被銷燬時被釋放掉。

2)函數

shared_ptr<T> sp;                默認構造
shared_ptr<T> sp(ptr);           建立一個shared_ptr,初始化爲ptr
shared_ptr<T> sp(ptr,del);       初始化ptr,析構函數爲del
shared_ptr<T> sp(ptr,del,ac);    初始化ptr,析構del用ac作爲內存分配器
shared_ptr<T> sp(nullptr);
shared_ptr<T> sp(nullptr,ptr);
shared_ptr<T> sp(nullptr,ptr,del);
shared_ptr<T> sp(sp2);           與sp2共享使用
shared_ptr<T> sp(move(sp2));     奪取sp2的使用權,sp2置空
shared_ptr<T> sp(sp2,ptr);       共享sp2,指向ptr
shared_ptr<T> sp(wp);            基於weak pointer wp創建的sp
shared_ptr<T> sp(move(up));      基於unique_ptr up創建的sp
shared_ptr<T> sp(move(ap));      基於auto_ptr up創建的sp
sp.~shared_ptr();                析構
sp = sp2;                        共享sp2
sp = move(sp2);                  sp2將擁有權交給sp,sp2 = nullptr
sp = move(up);                   up將擁有權交給sp,up= nullptr
sp = move(ap);                   ap將擁有權交給sp,ap= nullptr
sp.swap(sp2);                   置換sp1和sp2的pointer和delete
swap(sp1,sp2);                  置換sp1和sp2的pointer和delete
sp.reset();                     放棄擁有權並重新初始化,賦值爲空
sp.reset(ptr);                  放棄擁有權,重新初始化爲ptr
sp.reset(ptr,del);
make_shared(...);               爲一個新的對象建立對象
allocate_shared(ac,...);        爲新對象建立一個對象,使用allocate ac
sp.get(); 返回存儲的pointer(通常爲被擁有物的地址)
sp.use_count(); 返回共享對象的擁有者數量
sp.unique(); 返回sp是否是唯一擁有者 等同於 sp.use_count == 1
if(sp); 判斷sp是否爲空
sp1 == sp2 針對pointer 調用 ==
sp1 != sp2 針對pointer 調用 !=
sp1 <= sp2 針對pointer 調用 <=
sp1 >= sp2 針對pointer 調用 >=
sp1 < sp2 針對pointer 調用 <
sp1 > sp2 針對pointer 調用 >
static_pointer_case(sp); 對sp執行static_case<>
dynamic_pointer_case(sp); 對sp執行dynamic_case<>
const_pointer_case(sp); 對sp執行const_case<>
get_deleter(sp); 返回delete地址
sp.owner_befor(wp); 提供自己與 weak poinrter之間的strict weak ording

3)高層接口(線程安全)

atomic_is_lock_free(&sp);     如果sp的atomic接口是lock free 返回true
atomic_load(&sp);             返回sp
atomic_store(&sp,sp2);        將sp2賦值給sp
atomic_exchange(&sp,sp2);     交換sp和sp2的值

4)測試

#include <iostream>
#include <string>
#include <vector>
#include <memory>

using namespace std;

int main()
{
	//創建
	shared_ptr<string> pA(new string("AAA"));
	shared_ptr<string> pB(new string("BBB"));
	shared_ptr<string> pC;
	//只能共享指針 賦值共享指針,不允許隱式轉換 string 賦值共享指針
	//pC = new string("CCC");
	pC = pA;

	//自定義delete
	{
		shared_ptr<string> pE(new string("ABCDE"), [](string *p) {
			cout << "delete " << *p << endl;
			delete p;
		});

		//獲取智能指針的del
		auto del = [](string *p) {
			cout << "delete " << *p << endl;
			delete p;
		};
		shared_ptr<string> pF(new string("FFF"), del);
		decltype(del) *pd = get_deleter<decltype(del)>(pF);
		shared_ptr<string> pG(new string("GGG"), *pd);
	}
	//創建一個新的共享對象給pC
	pC = make_shared<string>("CCC");

	cout << "make_shared<string>(\"CCC\") " <<*pC << endl;
	string *str = new string("DDD");

	//重置 爲 str
	pC.reset(str);
	cout << "reset(str) " << *pC << endl;

	cout << "共享對象個數 " << pC.use_count() << endl;
	
	//改值
	(*pA)[0] = 'C';
	pB->replace(0, 1, "D");

	//存智能指針
	vector<shared_ptr<string>> vec;

	vec.emplace_back(pA);
	vec.emplace_back(pA);
	vec.emplace_back(pB);
	vec.emplace_back(pA);

	for ( auto ptr : vec)
	{
		cout << *ptr << ends;
	}
	cout << endl;
	
	//更改數據
	*pA = "CCC";	

	for (auto ptr : vec)
	{
		cout << *ptr << ends;
	}
	cout << endl;

	system("pause");
}

3、weak_ptr

weak_ptr用來共享對象但不擁有對象(不能對對象進行查看、更改等操作)。不計共享次數

1)weak_ptr可以爲空

創建未賦值;對象最後一個shared_ptr被刪除。

2)函數

weak_ptr<T> wp;             默認構造
weak_ptr<T> wp(sp);         共享被sp擁有的pointer的擁有權
weak_ptr<T> wp(wp2);        共享被wp2擁有的pointer的擁有權
wp.~weak_ptr();             析構,銷燬weak_ptr但不影響它所擁有的的對象
wp = wp2;                   賦值
wp = sp;                    賦值
wp.swap(wp2);               置換
swap(wp1,wp2);
wp.reset();                 放棄被擁有物的擁有權
wp.use_count();             返回擁有者shared_ptr的數量。如果weak_ptr等於空返回0
wp.expired();               返回 是否爲空
wp.lock();                  返回一個shared_ptr
wp.owner_before(wp2);       提供自己與另一個weak_ptr之間的 strict weak ordering
wp.owner_before(sp);        提供自己與另一個shared_ptr之間的 strict weak ordering

3)測試

#include <iostream>
#include <string>
#include <memory>

using namespace std;

int main()
{
	auto del = [](string *p) {	cout << *p << endl;	delete p; };
	shared_ptr<string> pA(new string("AAA"), del);

	cout << "*pA "<<*pA << endl;

	weak_ptr<string> wp;
	cout << "Whether weak_ptr is empty : " << wp.expired() << endl;

	wp = pA;
	cout << " use_count "<<wp.use_count() << endl;

	//返回一個shared_ptr對象
	shared_ptr<string> pB = wp.lock();
	cout << " use_count " << wp.use_count() << endl;

	pA.reset();
	pB.reset();
	cout << "pA.reset() and pB.reset()." << endl;
	cout << "Whether weak_ptr is empty : " << wp.expired() << endl;
	cout << " use_count " << wp.use_count() << endl;
	system("pause");
}

4、unique_ptr

C++11提供的,一種在異常發生時可以避免資源泄露的智能指針。它確保一個資源在同一時間只被一個pointer所擁有。當指針被銷燬、空、或指向別處時,先前擁有的對象被銷燬,資源被釋放。

1)函數

unique_ptr<...> up;              默認構造
unique_ptr<...> up(nullptr);     建立一個空的unique_ptr
unique_ptr<...> up(ptr);         建立unique_ptr,初始化爲ptr
unique_ptr<...> up(ptr,del);     建立unique_ptr,初始化爲ptr,析構爲del
unique_ptr<...> up(move(up2));   up取代up2,up2爲空
unique_ptr<...> up(move(ap));    up取代ap,ap爲空
up.~unique_ptr();                析構
up = move(up2);
up = nullptr;
up1.swap(up2);
swap(up1,up2);
up.reset();                     刷新,置空
up.reset(ptr);                  刷新,置爲ptr
up.release();                   放棄擁有權,不調用delete
up.get();                       返回pointer
if(up);                         判斷是否爲空
up1 == up2; 
up1 != up2;
up1 <= up2;
up1 >= up2;
up1 < up2;
up1 > up2;
up.get_deleter();               放回del的引用

2)測試

#include <iostream>
#include <string>
#include <memory>

using namespace std;

int main()
{
        //自定義 del
	auto del = [](string *p) { cout << *p << endl; delete p; };

	{
		//創建 
		unique_ptr<string, decltype(del)> pA(new string("AAA"), del);
	}
	
	{	//數組類型的聲明方式 delete[]
		unique_ptr<string[]> pB(new string[10]);
		//針對數組,不再提供*和->,改用[]
		//默認析構 delete[]
		//不支持不同類型之間的轉換。不允許指向派生元素類型
	}
	
	string *str = new string("CCC");
	unique_ptr<string> pC(str);
	pC.release(); //放棄擁有權,不調用delete
	cout << *str << endl;

	system("pause");
}

 

發佈了42 篇原創文章 · 獲贊 52 · 訪問量 6572
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章