第十二章 動態記憶體

2021-08-08 23:47:15 字數 3239 閱讀 8179

程式除靜態記憶體和棧記憶體,還有自由空間(free store)or 堆(heap)。

使用動態記憶體容易造成記憶體洩漏:忘記delete new分配的空間。

share_ptr類:模板。最好用make_shared函式來分配記憶體。

shared_ptr

p1 = make_shared ();

shared_ptr

p2 = make_shared (6, '6');

shared_ptr

p3(p1);//允許多個指標指向同乙個物件,shared

refrence count:比較重要,變為0,自動銷毀管理物件,釋放相關記憶體。 拷貝遞增,賦新值或銷毀時遞減,如區域性shared_ptr離開其作用域。(注:將shared_ptr存入容器,而後不在需要全部元素,記得erase。)

類使用動態記憶體:1 不知道自己需要使用多少物件——容器類。 2 不知道物件準確型別。 3 多個物件間共享資料——類成員引用相同的底層資料,只有當引用計數為0時銷毀底層資料。

釋放一塊非new分配記憶體或者同一記憶體釋放多次,undefined。

然而釋放乙個空指標總沒錯:*p0 = nullptr; delete p; //ok

空懸指標(dangling pointer):delete之後,指標任然儲存記憶體位址,即它指向一塊曾經儲存資料但現在已經無效的記憶體。最好:

int *p = new int(666); delete p; p = nullptr; //指標置空

但是多指標指向同一記憶體時要多加小心。

shared_ptr

p1 = new

int(666);//error:不能將內建指標隱式轉換為智慧型指標

shared_ptr

p2(new

int(666)); //ok;直接初始化

/*特別是在函式返回型別為智慧型指標時要注意*/

shared_ptr

func1(int p)

//wrong!

shared_ptr

func2(int p)

//ok!

void process(shared_ptr

ptr)

/*當傳遞給該函式乙個shared_ptr型別引數時,引用計數至少為2*/

shared_ptr

p1(new

int(666)); //引用計數1

process(p1);//拷貝,函式中引用計數2,p1離開作用域銷毀,變為1,並未釋放記憶體,p1仍然指向分配的記憶體,可繼續使用,注意後續處理。

/*當傳遞給該函式乙個內建指標時*/

int *p2(new

int(666));

process(p2);//error:不能隱式轉化

process(shared_ptr

(p2));//ok,用完之後引用計數就為0了,記憶體已經釋放!

使用get()時需注意,get()返回指標的**不能delete此指標,否則原來的shared_ptr將變成空懸指標。不要用get()初始化或為另乙個智慧型指標賦值。

reset():

if (!p.unique()) //檢查我們是否是當前物件的唯一使用者 

p.reset(new

int(*p));//不是,分配新的拷貝

//現在是唯一使用者,操作p

智慧型指標確保發生異常時的資源釋放:

void func1()

//函式結束時,自動釋放資源

void func2()

使用智慧型指標管理的不是new分配的記憶體,要傳遞給它乙個刪除器:

shared_ptr

p(i, c);//c是執行析構操作的可呼叫物件,是我們自定義的刪除器

unique_ptr不支援普通的拷貝或賦值操作,可以拷貝或賦值乙個將要被銷毀的unique_ptr,例如從函式返回乙個unique_ptr。注意release()方法並未呼叫delete。

unique_ptr p1 = new

int(666);

p1.release();//並未釋放記憶體,不要這樣用

auto p = p1.release();

delete p;//釋放了記憶體

weak_ptr繫結到shared_ptr來觀察物件,不改變引用計數,不能用來直接訪問物件,因為有可能物件不存在,需呼叫lock()方法:

shared_ptr

p = new

int(666);

weak_ptr wp(p);

if (shared_ptr

p1 = wp.lock())

盡量使用標準庫容器而不是動態分配的陣列!

分配乙個陣列,得到的是乙個陣列元素型別的指標,並非乙個陣列型別的物件!

int *p = new

int [num]();//最好初始化一下

delete p;

char arr[0] //error:不能定義長度為0的陣列

char *cp = new

char[0]; //ok,動態分配乙個空陣列是合法的,

//但不能解引用cp

unique_ptr p(new

int[10]);//unique_ptr直接管理動態陣列

p.release();//書上說這裡會自動呼叫delete,因為管理的是乙個陣列

shared_ptr

p1(new

int[10], (int *p) );

//shared_ptr管理動態陣列需傳遞乙個刪除器,沒有定義,智慧型指標不支援指標算術運算,get()內建指標來訪問陣列元素。

allocator類:分配原始的、未構造的記憶體,將分配記憶體與物件構造分離開來,提高靈活性。

allocator alloc;//可以為string物件分配記憶體

auto p = alloc.allocate(num);//分配num個string物件

//construct()方法構造;

//destroy()方法銷毀;

//deallocate()釋放記憶體;先destroy再釋放

//相關演算法,copy,fill;

第十二章動態記憶體 allocator類

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

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

第十二章 動態記憶體 1.動態記憶體 c 中,動態記憶體管理是通過一對運算子完成的 new和delete。c語言中通過malloc與free函式來實現先動態記憶體的分配與釋放,c 中new與delete的實現其實會呼叫malloc與free。由於 c 語言沒有自動記憶體 機制,每次 new 出來的記...

第十二章 動態規劃 2019 04 01

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