程式除靜態記憶體和棧記憶體,還有自由空間(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 無後效性。指的是某狀態下決策的收益,...