智能指針是存儲動態(tài)分配對象指針的類,用于生命周期的控制。當(dāng)指針離開其作用域時赏陵,自動銷毀動態(tài)分配的空間,防止內(nèi)存泄漏饲漾。
使用智能指針需要包含頭文件#include<memory>
shared_ptr
std::shared_ptr采用引用計數(shù)蝙搔,每一個shared_ptr的拷貝都指向相同的內(nèi)容,當(dāng)最后一個shared_ptr析構(gòu)的時候考传,內(nèi)存被釋放
初始化shared_ptr對象
#include<iostream>
#include<memory>
int main(){
std::shared_ptr<int> p1(new int(1)); //方式1
std::shared_ptr<int> p2 = p1; //方式2
std::shared_ptr<int> p3;
//方式3 reset吃型,如果原有的shared_ptr不為空,會使原對象的引用計數(shù)減1
p3.reset(new int(1));
//方式4
std::shared_ptr<int> p4 = std::make_shared<int>(2);
//使用方法例子:可以當(dāng)作一個指針使用
std::cout << *p4 << std::endl;
//std::shared_ptr<int> p4 = new int(1);
if(p1) { //重載了bool操作符
std::cout << "p is not null" << std::endl;
}
int* p = p1.get();//獲取原始指針
std::cout << *p << std::endl;
}
指定刪除器
當(dāng)使用shared_ptr刪除數(shù)組時僚楞,需要指定刪除器
常用的寫法有以下幾種
#include<iostream>
#include<memory>
template<typename T>
std::shared_ptr<T> make_shared_array(size_t size) {
return std::shared_ptr<T>(new T[size], std::default_delete<T[]>());
}
int main(){
//lambda
std::shared_ptr<int> p(new int[10], [](int* p){delete [] p;});
//指定默認(rèn)刪除器
std::shared_ptr<int> p1(new int[10], std::default_delete<int[]>());
//自定義泛型方法
std::shared_ptr<char> p2 = make_shared_array<char>(10);
}
使用的注意事項
不要用一個原始指針初始化多個shared_ptr
不要在函數(shù)實參中創(chuàng)建shared_ptr勤晚。
如下面中的例子枉层。
//不同編譯器執(zhí)行結(jié)果可能不同
//如果以new int -> 調(diào)用g() -> 創(chuàng)建shared_ptr的順序
//那么假如g()方法失敗,直接導(dǎo)致內(nèi)存泄漏
void f(shared_ptr<int>(new int), g())
通過shared_from_this()返回this指針時赐写,不要作為shared_ptr返回览濒,因為this是一個裸指針葫录,可能會導(dǎo)致重復(fù)析構(gòu)妙真。如下面例子中灯萍,sp1和sp2重復(fù)析構(gòu)A對象,導(dǎo)致錯誤悠夯。如果需要返回this指針癌淮,可以通過繼承enable_shared_from_this類躺坟,調(diào)用方法shared_from_this實現(xiàn)沦补。如下面中注釋掉的寫法。
如果
#include<iostream>
#include<memory>
class A {
public:
std::shared_ptr<A> GetSelf() {
return std::shared_ptr<A>(this);
}
};
/*
class A :public std::enable_shared_from_this<A>{
public:
std::shared_ptr<A> GetSelf() {
return shared_from_this();
}
};
*/
int main(){
std::shared_ptr<A> sp1(new A);
std::shared_ptr<A> sp2 = sp1 -> GetSelf();
}
要注意循環(huán)引用帶來的內(nèi)存泄漏問題咪橙。如下面A與B循環(huán)引用夕膀,導(dǎo)致內(nèi)存泄漏
#include<iostream>
#include<memory>
struct A;
struct B;
struct A {
std::shared_ptr<B> bptr;
~A() {
std::cout << "A is delete" << std::endl;
}
};
struct B {
std::shared_ptr<A> aptr;
~B() {
std::cout << "B is delete " << std::endl;
}
};
int main(){
std::shared_ptr<A> ap(new A);
std::shared_ptr<B> bp(new B);
ap->bptr = bp;
bp->aptr = ap;
}