動態記憶體與智慧型指標

2021-08-01 22:40:25 字數 3794 閱讀 1041

智慧型指標與常規指標的區別在於它自動釋放所指向的物件。

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物件在第一次使用前分配,在程式結束時銷毀。區域性自動物件,在進入其定義所在的程式塊兒時被建立,離開塊時銷毀。即,它們都是由編譯器自動建立與銷毀。而動態分配的物件的生存期與它們在 建立的無關,只有當顯式地被釋放...