c primer第十二章動態記憶體小結 12

2021-07-24 09:38:26 字數 3271 閱讀 1134

第十二章---動態記憶體

1.動態記憶體

c++中,動態記憶體管理是通過一對運算子完成的:new和delete。c語言中通過malloc與free函式來實現先動態記憶體的分配與釋放,

c++中new與delete的實現其實會呼叫malloc與free。由於 c++ 語言沒有自動記憶體**機制,每次 new 出來的記憶體都要手動 delete。

程式設計師忘記 delete,流程太複雜,最終導致沒有 delete,異常導致程式過早退出,沒有執行 delete 的情況並不罕見。

new運算其實分為三個部分,

a.首先呼叫operator new函式分配足夠大的為型別化的記憶體空間以儲存指定型別的乙個物件,

b.然後執行該物件的建構函式,初始化該物件,

c.最後返回指向新分配記憶體空間的指標

我們可以過載operator new函式,人為地進行記憶體分配,達到優化記憶體的效果。在類中一旦出現過載的operator new函式,則系統不

再呼叫標準庫的operator new函式。

delete運算使用時分為兩個步驟,

a.首先呼叫指定物件的析構函式

b.然後呼叫名為operator delete的標準庫函式釋放該物件所占用的記憶體。

c.指標置null.否則成為野指標。

operator delete函式同樣可以過載。當使用new新建乙個動態物件以後需要使用assert判斷動態建立是否成功,以防止程式執行時對

未建立的物件進行使用。delete陣列時需使用註明。如果動態建立乙個陣列而使用了delete去釋放它,會導致只有陣列中第乙個素

被釋放,出現記憶體洩漏。

2.智慧型指標

用智慧型指標便可以有效緩解上述問題,

c++11新標準提供了兩種智慧型指標,負責自動釋放所指向的物件。

shared_ptr允許多個指針指向同乙個物件

unique_ptr則"獨佔"所指向的物件

標準庫還定義了乙個名為weak_ptr的伴隨類;

這三種型別都定義在memory頭

檔案中。

對於編譯器來說,智慧型指標實際上是乙個棧物件,並非指標型別,在棧物件生命期即將結束時,智慧型指標通過析構函式釋

放有它管理的堆記憶體。所有智慧型指標都過載了「operator->」操作符,直接返回物件的引用,用以操作對

象。訪問智慧型指標原來的方法

則使用「.」操作符。

訪問智慧型指標包含的裸指標則可以用 get() 函式。由於智慧型指標是乙個物件,所以if (my_smart_object)永遠為真,要判斷智慧型指標的裸指標是否為空,需要這樣判斷:if (my_smart_object.get())。

智慧型指標包含了 reset() 方法,如果不傳遞引數(或者傳遞 null),則智慧型指標會釋放當前管理的記憶體。如果傳遞乙個物件,則智慧型指標會釋放當前物件,來管理新傳入的物件。

3.使用智慧型指標的一些注意事項

3.1 接受指標引數的智慧型指標建構函式是explicit(避免只有乙個引數的函式進行隱式轉換)的,我們不能將乙個內建指標隱式轉換為乙個智慧型指標。 直接初始初始化可以。

3.2 為了向不能使用智慧型指標的**傳遞乙個內建指標,智慧型指標定義了乙個名為get的函式,返回乙個普通型別的指標,使用get返回的指標的**不能delete此指標,因為智慧型指標會刪除,手動刪除會造成二次刪除

3.3 將乙個智慧型指標繫結到get返回的指標也是錯誤的。永遠不要用get初始化另乙個智慧型指標或者為另乙個智慧型指標賦值。因為普通指標不能自動轉化為智慧型指標。

3.4 

當將乙個shared_ptr 繫結到乙個普通指標時,我們就將記憶體管理交給了shared_ptr,之後我們就不應該使用內建指標來訪問shared_ptr指向的內存了。

使用內建指標來訪問智慧型指標所附則的物件是非常危險的,我們不知道物件何時被銷毀。

4.share_ptr

make_shared是乙個非成員函式,具有給共享物件分配記憶體,並且只分配一次記憶體的優點,和顯式通過建構函式初始化(new)的

shared_ptr相比較,後者需要至少兩次分配記憶體。這些額外的開銷有可能會導致記憶體溢位的問題,最安全的使用動態記憶體的方法是使

用乙個make_shared的函式。此函式在動態記憶體中分配乙個物件並初始化,返回指向此物件的shared_ptr。我們可以認為每個

shared_ptr都有乙個關聯的計數器,通常稱其為引用計數,無論我們拷貝乙個share_ptr,計數器都會遞增。當我們給乙個shared_ptr

賦值或者shared被銷毀,計數器就會遞減。當用乙個shared_ptr初始化另外乙個shared_ptr,或將它作為引數傳遞給乙個函式以及作

為函式的返回值(賦值給其他的),計數器都會遞增一旦乙個share_ptr的計數器變為0,它就會釋放自己所管理的物件!注意標準庫

是用計數器還是其他資料結構來記錄有多少個指標共享物件由標準庫來決定,關鍵是智慧型指標類能記錄有多少個shared_ptr指向相同

的物件,

並能在恰當的時候自動釋放物件。

5.unique_ptr

乙個unique_ptr 擁有它所指向的物件,和shared_ptr不同,某個時刻只能有乙個unique_ptr 指向乙個給定物件,當unique_ptr 被銷毀

時,物件也被銷毀,unique沒有類似make_shared,必須手動new,將其繫結,由於unique_ptr獨佔它所指向的物件,因此他不支援普通

的拷貝和賦值.但是有種特殊的拷貝可以支援:我們可以拷貝或賦值乙個即將要被銷毀的unique_ptr。

6.weak ptr 

它指向由乙個shared_ptr 管理的物件,當我們建立乙個weak_ptr 必須用乙個 shared_ptr 初始化。引入lock和expired是防止在weak_ptr 不知情的情況下,shared_ptr 被釋放掉,weak_ptr 不會更改shared_ptr 的引用計數。

第十二章 動態記憶體

程式除靜態記憶體和棧記憶體,還有自由空間 free store or 堆 heap 使用動態記憶體容易造成記憶體洩漏 忘記delete new分配的空間。share ptr類 模板。最好用make shared函式來分配記憶體。shared ptr p1 make shared shared ptr...

第十二章動態記憶體 allocator類

new和delete的兩部分操作 記憶體分配 釋放 和物件構造 析構 當分配一大塊記憶體時,我們計畫在這塊記憶體上按需構造物件,在此情況下希望記憶體分配和物件構造分離。這表示 我們可以分配大塊記憶體,但是只有真正需要時才執行物件建立操作 同時付出一定開銷 將記憶體分配和物件構造組合在一起可能會導致不...

第十二章 動態規劃 2019 04 01

1 最優化原理,也就是最優子結構性質。這指的是乙個最優化策略具有這樣的性質,不論過去狀態和決策如何,對前面的決策所形成的狀態而言,餘下的諸決策必須構成最優策略。簡單來說就是乙個最優化策略的子策略總是最優的,如果乙個問題滿足最優化原理,就稱其具有最優子結構性質。2 無後效性。指的是某狀態下決策的收益,...