目錄
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");
}