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數組
*
*
*其他:引用計數算在內的指針叫強引用。
*
*/