智慧型指標與常規指標的區別在於它自動釋放所指向的物件。
shared_ptr:允許多個指標指向同乙個物件
unique_ptr:「獨佔」所指向的物件。
weak_ptr:伴隨類,弱引用,指向shared_ptr所管理的物件。
//定義,與vector類似,智慧型指標也是模板
shared_ptr
p1;
shared_ptr
> p2;
make_shared函式:最安全的分配和使用動態記憶體的方法,此函式在動態記憶體中分配乙個物件並初始化它,返回指向此物件的shared_ptr。
//定義乙個智慧型指標p3,指向值為42的int。
shared_ptr
p3=make_shared(42);
//指向乙個值初始化的int
shared_ptr
p4=make_shared();
可認為每個shared_ptr有乙個關聯計數器,通常稱為引用計數。
auto p=make_shared(42);//p指向的物件之一p乙個引用
auto q(p);//q,p指向同乙個物件,此物件有2個引用
auto r=make_shared(42);
r=q;//遞增q的引用計數,遞減r的引用計數,r原來的物件已經沒有引用者,會自動釋放
shared_ptr
factory(t arg)
void use_factory(t arg)
//p離開了作用域,它指向的記憶體會被自動釋放掉
程式使用動態記憶體的三個原因:
定義strbob類實現共享資料
class strbob
bool empty()const
void push_back(const
string &t)
void pop_back();
string &front();
string &back();
private:
shared_ptr
> data;
//如果data[i]不合法,丟擲異常
void check(size_type i,const
string &msg)const;
}
strbob::strbob():data(make_shared>()){}
strbob::strbob(initializer_list il)
data(make_shared>(il)){}
void strbob::check(size_type i,const
string &msg)const
int *p1=new
int;//預設初始化,*p1的值未定義
int *p2=new
int();//值初始化為0
auto p3=new
auto(obj);//p指向乙個與obj同型別的物件
用new分配const物件是合法的
const
int *p=new
const
int(1024);//乙個動態分配的const物件必須初始化,對於定義了預設建構函式的類型別,可以隱式初始化,其他必須顯示初始化。
int *p1=new
int;//如果分配失敗,丟擲異常
int *p2=new(nothrow) int;//如果分配失敗,new返回乙個空指標,這種new稱為定位new
shared_ptr p1=new
int(1024);//錯誤,接收指標引數的智慧型指標引數是explicit的,因此無法將常規指標隱式轉換成智慧型指標,所以只能直接初始化
shared_ptr p2(new
int(1024));//正確
當我們定義乙個unique_ptr時,需要將其繫結到乙個new返回的指標上,初始化unique_ptr必須採用直接初始化
unique_ptr p1;
unique_ptr p2(new
int(42));
由於unique_ptr「獨佔」物件,因此不支援拷貝和賦值。
unique_ptr p2(p1.release());//將物件所有權從p1轉為p2
p2.reset(p3.release());////將物件所有權從p3轉為p2,同時reset釋放了p2原來的記憶體
unique_ptr因此不能拷貝有個例外,可以拷貝或賦值乙個即將要被銷毀的unique_ptr
unique_ptr clone(int p)
weak_ptr是一種不控制物件生存期的智慧型指標,它指向shared_ptr 管理的物件,且不會改變shared_ptr的引用計數。被銷毀的物件即使有weak_ptr指向物件,還是會被銷毀。
auto p=make_shared(42);
weak_ptr wp(p);//wp弱共享p
lock檢查weak_ptr指向的物件是否存在。
if(shared_ptr np=wp.lock())//如果不為空,條件成立
int *pia=new
int[get_size()];//pia指向第乙個int
typedef
int arrt[42];
int *p=new arrt;
delete p;//釋放乙個動態分配的物件
delete p; //釋放動態陣列
unique_ptr管理動態陣列
unique_ptr up(new
int[10]);//
for(size_t i=0;i!=10;i++)
up.release();//自動呼叫delete銷毀其指標
shared_ptr不直接支援管理動態記憶體,如果希望shared_ptr管理動態陣列,必須為其提供自己定義的刪除器
shared_ptr
sp(new int[10],(int *p))
sp.reset();//呼叫我們提供的lambda釋放陣列
//shared_ptr未定義下標運算子,並且不支援指標的算術運算子
for(size_t i=0;i!=10;++i)
*(sp.get()+i)=i;//使用get獲得乙個內建指標
allocator類將記憶體分配和物件構造分開,它分配的記憶體是原始的,未構造的。alloctor是乙個模板
allocator alloc;
auto
const p=alloc.allocte(n);
auto q=p;
alloc.construct(q++);
alloc.construct(q++,10,'c');
alloc.construct(q++,"hi");//一定要在構造之後使用記憶體
while(q!=p)
alloc.destroy(--q);//銷毀物件
alloc.deallocate(p,n);//釋放記憶體
動態記憶體與智慧型指標
動態記憶體與智慧型指標 靜態記憶體用來儲存區域性static物件 類static資料成員以及定義在任何函式之外的變數 全域性變數 棧記憶體用來儲存定義在函式內的非static物件。分配在靜態或棧記憶體中的物件由編譯器自動建立和銷毀。對於棧物件,僅在其定義的程式塊執行時才存在 static物件在使用之...
動態記憶體與智慧型指標
在c 中,動態記憶體的管理是通過一對運算子來完成的 new,在動態記憶體中為物件分配空間並返回乙個指向該物件的指標,我們可以選擇對物件進行初始化 delete,接受乙個動態物件指標,銷毀該物件並釋放與之關聯的記憶體。動態記憶體在使用時很容易出問題,有時會忘記釋放記憶體,造成記憶體洩露,有時在尚有指標...
動態記憶體與智慧型指標
我們先來看一些物件的生存期。全域性物件在程式啟動時分配,在程式結束時銷毀。區域性static物件在第一次使用前分配,在程式結束時銷毀。區域性自動物件,在進入其定義所在的程式塊兒時被建立,離開塊時銷毀。即,它們都是由編譯器自動建立與銷毀。而動態分配的物件的生存期與它們在 建立的無關,只有當顯式地被釋放...