5-3 shared_ptr常用操作、計數、自定義刪除器等等

003share_ptr的引用和減少與常見操作

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

using namespace std;

class A
{
public:
	A()
	{}
	~A()
	{
		
	}
};

//void myfunction(shared_ptr<int>&myp)//使用引用,引用計數不會增加
void myfunction(shared_ptr<int>myp)
{
	cout << "智能指針做函數參數,引用計數增加" << endl;
}

shared_ptr<int> myfunction02(shared_ptr<int>&myp)
{
	cout << "智能指針做函數返回值,引用計數增加" << endl;
	return  myp;
}


void mydelete(int*p)//自己指定的刪除器
{
	cout << "這是我們自己定義的刪除器" << endl;
	//......
	delete p;
}

//3.函數模板封裝
template<typename T>
shared_ptr<T>make_shared_array(size_t size)
{
	return shared_ptr<T>(new T[size], default_delete<T[]>());
}


int main(void)
{
	//1引用用計數的增加
	auto p1 = make_shared<int>(100);//int =100對象只有一個引用者,p1
	auto p2(p1);//兩個引用者p1,p2		2 strong refs
	myfunction(p2);//把智能指針當做函數實參傳遞給函數 --引用計數增加1
	//作爲函數實參傳遞,會增加引用
	auto p3 = myfunction02(p2);


	//2引用計數的減少
	auto p4 = make_shared<int>(400);//p4指向新對象,p4引用計數爲1
	p1 = make_shared<int>(500);//p1引用計數減少爲1

		//3.當一個shared_ptr類型的指針從1變爲0,他會自動釋放自己所管理(指向)的對象
	auto p5 = make_shared<int>(1000);
	auto p6 = make_shared<int>(1000);
	p6 = p5;//這是是賦值,p6的引用計數變爲2, p5引用計數變爲2,


	//shared_ptr返回有多少個智能指針指向某個對象
	int myCount = p6.use_count();
	cout << myCount << endl;	//2
	int myCount02 = p5.use_count();
	cout << myCount02 << endl;	//2

	//2.unique(*)是否該智能指針獨佔指向某個對象,返回true或者false
	shared_ptr<int> p7(new int(7));
	if (p7.unique())
	{
		cout << "unique成立,只有p7指向一塊內存對象" << endl;
	}

	//reset不帶參數,復位,置空
	shared_ptr<int> p8(new int(8));
	auto p9(p8);
	p8.reset();
	if (p8==nullptr)
	{
		cout << "p8指針爲空" << endl;
	}
	//reset帶參數new一個新對象
	shared_ptr<int> p10(new int(10));
	p10.reset(new int(11));//釋放原來內存,指向新的內存

	//空指針也可以使用reset重新初始化
	shared_ptr<int>p11;
	p1.reset(new int(11));
	
	//4解引用
	shared_ptr<int>p12(new int(12));
	cout << *p12 << endl;
	
	//get()返回指針
	shared_ptr<int>p13(new int(13));
	int*p14 = p13.get();
	cout << *p14 << endl;
	//這裏不要手工釋放p14,它指向的內存空間歸智能指針p13管理

	//swap()
	shared_ptr<string> p15(new string("aaaa"));
	shared_ptr<string> p16(new string("bbbb"));
	swap(p15, p16);
	cout << *p15 << endl;//bbbb
	cout << *p16 << endl;//aaaa

	//=nullptr
	p15 = nullptr;

	//智能指針名字作爲判斷條件
	if (p16)
	{
		cout << "p16指向一個對象" << endl;
		p16 = nullptr;
		
	}

	//指定自定定義的刪除器
	shared_ptr<int>p17(new int(17), mydelete);
	p17 = nullptr;//調用自己寫的刪除器,自己需要在函數裏面進行內存的釋放
	//刪除器可以是一個lambda表達式
	shared_ptr<int>p18(new int(18), [](int*p) {delete p; });


	//有些情況下,默認刪除器處理不了---動態數組
	shared_ptr<int>p19(new int[10], [](int*p) {delete[]p; });

	//可以使用default_delete來做刪除器,default_delete是標準庫裏面的模板類
	shared_ptr<A>pA(new A[10], std::default_delete<A[]>());//加上[]表示是刪除的一個數組

	//c++17  定義數組的時候在<>中添加[]

	//shared_ptr<A[]>pA2(new A[10]);//這樣c++17可以正常處理數組的釋放問題


	//shared_ptr模板封裝
	shared_ptr<int>p20 = make_shared_array<int>(5);
	
	system("pause");
	return 0;
}

/*
*(1)shared_ptr引用計數的增加和減少
*共享式指針--引用計數--每一個shared_ptr都指向相同的內存,最後一個指針負責釋放。
*	1.引用計數的增加
*	每個shared_ptr都會記錄有多少其他的shared_ptr指針指向相同的對象。
*	在如下情況下:所有指向這個兌現的shared_ptr引用計數都會增加1:
*		使用一個指針初始化另一個指針
*		把智能指針當做函數實參傳遞給函數(使用引用,引用計數不會增加)
*		作爲函數返回值
*	2.引用計數的減少
*		1.給shared_ptr賦予新的值,讓shared_ptr指向一個新的對象
*		2.局部的shared_ptr離開引用
*		3.當一個shared_ptr類型的指針從1變爲0,他會自動釋放自己所管理(指向)的對象
*		
*(2)shared_ptr類型指針的常用操作
*	1.shared_ptr返回有多少個智能指針指向某個對象
*	2.unique(*)是否該智能指針獨佔指向某個對象,返回true或者false
*	3.reset()復位,恢復,重置
*		reset()不帶參數,那麼指針是唯一指向的指針,那麼釋放指向的內存空間,並將指針置空
*				若不是指向該對象的唯一指針,那麼引用該對象的引用計數會減少,同時將指針置空。
*		reset()帶參數,參數一般是new出來的指針,
*			若指針是唯一指針,則釋放指針指向的對象,讓指針指向新對象
*			若指針不是唯一指針,則不釋放指針,引用計數減少1,指向新對象
*	4.解引用,使用*或者指針指向的內容
*	5.get返回p中保存的指針,如果智能指針釋放了所指向的對象,返回的裸指針也就沒有意義。
*		因爲有些第三方庫的函數參數,有的需要一個裸指針,而不是智能指針
*	6.swap()交換兩個智能指針所指向的對象
*	7.=nullptr指向空
*		1.將指針的引用計數減少1,若引用計數減少爲0,則釋放指針指向的對象
*		2.將智能指針置空
*	8.智能指針名字作爲判斷條件
*	9.指定刪除器和數組問題
*		一定時機,智能指針會幫助我們刪除所指向的對象,將delete運算符作爲默認的資源析構方式。
*		如果我們有自己的需求,可以指定自己的刪除器取代系統提供的默認刪除器。
*		shared_ptr在參數中添加具體的刪除器函數名字即可。
*
*	指定刪除器額外說明:
*		******就算兩個share_ptr指定了不同的刪除器,但是隻要他們執行的對象類型相同,這連個share_ptr類型指針就是同一個類型。
*			類型相同,就代表可以放到元素類型爲該對象類型的容器裏來。
*			
*		make_shared是提倡的方法,但是不能生成自己的刪除器。
*(3)函數模板來封裝shared_ptr數組
*
*
*其他:引用計數算在內的指針叫強引用。
*
*/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章