C 知識點34 動態記憶體與智慧型指標

2021-10-24 22:07:20 字數 3087 閱讀 6001

一、動態記憶體

動態記憶體所在的位置在堆區,由程式設計師手動分配並手動釋放,而不像棧記憶體由系統分配和自動釋放

c++通過new運算子為物件在堆上分配記憶體空間並返回該物件的位址,並用delete運算子銷毀物件並釋放物件所佔的動態記憶體,如果分配動態記憶體後沒有手動釋放會產生記憶體洩露

new乙個物件時分為三步:1、呼叫operator new或operator new來分配記憶體空間。分配記憶體空間這一步,實質上呼叫的是malloc。2、編譯器呼叫建構函式構造物件。3、構造完成後,返回乙個指向物件的指標

delete時,分為兩步:呼叫指標所指物件的析構函式銷毀物件。2、呼叫operator delete或者operator delete釋放記憶體空間,**記憶體空間這一步,實質上也是呼叫的是free

示例

void newexample()

; cout<

上面的**說明了如何用new動態分配記憶體並建立物件,如果new後邊的型別名後邊沒有括號,那麼將建立乙個預設初始化的物件,如果new後邊的型別名有大括號,則建立了乙個列表初始化的物件,如果new後邊的型別名帶有小括號,則是按照建構函式的形式進行直接初始化

但是上邊的**將產生記憶體洩漏,因為pi,ps,pi1,ps1,pv都是區域性變數,當函式執行結束後,區域性變數(這些指標)將被自動釋放,所以,之後再也沒有任何指標能指向並釋放new建立的物件的記憶體,也就造成了記憶體洩露,解決辦法就是在函式退出之前使用delete運算子釋放指標所指向的物件記憶體

delete pi, pi1, ps, ps1, pv;

如果函式返回乙個指向動態記憶體的指標,那麼接收該指標的拷貝的物件要負責釋放指向的記憶體

指標被delete後,指標變為空懸指標(指向記憶體中的資料已經無效),避免空懸指標的辦法就是delete指標後將指標置為空,這樣在使用前對指標判空就能知道指標不可以再解引用。但是這個辦法也是有限的

示例

void danglingpointer()

; string *p3=new string[10];

string *p4=new string[10]();

}

其中,第三行和第五行對10個元素進行預設初始化,第四行是列表初始化,第六行是值初始化

上面的**也是存在記憶體洩露的,只不過在用delete釋放資源時,語法不同

delete p1;

delete p2;

delete p3;

delete p4;

需要在delete和指標之間加上方括號當用new建立陣列時,方括號中的數字可以小於0,知道有這麼個東西就行,實際寫**不要這樣寫

此外,無論是用new建立單個物件還是物件的陣列,返回的都是物件型別的指標,c/c++中,指標並不知道指向的是單個物件還是物件的陣列

二、智慧型指標

當使用區域性變數的指標指向new建立的物件時,容易產生記憶體洩露,而應對措施有限,所以為了防止記憶體洩露,c++設計了三個智慧型指標:share_ptr, weak_ptr,  unique_ptr,使用這三個智慧型指標之前,要#include

2.1 shared_ptr

shared_ptr是c++標準庫中的模板,允許多個shared_ptr物件同時指向乙個物件,內部通過引用計數得到有多少個shared_ptr物件指向該物件,當最後乙個shared_ptr物件被銷毀時,被指向的物件會自動銷毀,將所佔的記憶體釋放。

2.1.1 shared_ptr的常用建構函式

constexpr shared_ptr() noexcept;

constexpr shared_ptr(nullptr_t) : shared_ptr() {}

template explicit shared_ptr (u* p);

template shared_ptr (u* p, d del);

template shared_ptr (nullptr_t p, d del);

shared_ptr (const shared_ptr& x) noexcept;

template shared_ptr (const shared_ptr& x) noexcept;

template explicit shared_ptr (const weak_ptr& x);

template shared_ptr (unique_ptr&& x);

示例

void shareptr()

explicit unique_ptr (pointer p) noexcept;

unique_ptr (pointer p, typename conditional::value,d,const d&> del) noexcept;

unique_ptr (const unique_ptr&) = delete;//拷貝和賦值都是delete,拷貝元素和賦值運算被禁用,所以unique_ptr不支援拷貝和賦值運算

unique_ptr& operator= (const unique_ptr&) = delete;

雖然unique_ptr不支援拷貝和賦值操作,但是還是有辦法將乙個unique_ptr的所占有的資源轉移給別的unique_ptr,那就是使用std::move

template typename remove_reference::type&& move (t&& arg) noexcept;
示例

void uniqueptrinit()

); list*lp2=ulp.release();

cout<

up[0]=10;

ulp.reset();//等價於reset(nullptr)

參考《c++ primer》

《c++標準庫》

C 動態記憶體與智慧型指標

qq 1841545843 郵箱 jiaxx903 163.com 靜態記憶體用來儲存區域性 static 物件 類的 static 資料成員,以及定義在任何函式之外的變數。棧記憶體用來儲存定義在函式之內的 static 物件。除了棧記憶體和靜態記憶體外,每個程式還擁有乙個記憶體池,這部分稱之為 堆...

c 動態記憶體與智慧型指標

目前為止我們學過靜態記憶體和棧記憶體,分配在其中的物件由編譯器自動建立和銷毀,靜態記憶體 用來儲存區域性static物件 類的static資料成員 以及定義在任何函式體之外的變數。在物件使用之前分配,程式結束時銷毀。棧記憶體 用來儲存定義在函式內的非static物件。僅在物件定義的程式塊執行時存在,...

動態記憶體與智慧型指標

動態記憶體與智慧型指標 靜態記憶體用來儲存區域性static物件 類static資料成員以及定義在任何函式之外的變數 全域性變數 棧記憶體用來儲存定義在函式內的非static物件。分配在靜態或棧記憶體中的物件由編譯器自動建立和銷毀。對於棧物件,僅在其定義的程式塊執行時才存在 static物件在使用之...