- 生存期
- 全局對象:程序啟動時分配无蜂,程序結(jié)束時銷毀
- 局部對象:進入其定義所在的程序塊時被創(chuàng)建,離開塊時被銷毀
- static對象:第一次使用前被分配,程序結(jié)束時銷毀
- 動態(tài)分配的對象:只有當顯式地被釋放時柜候,才會被銷毀
- 程序內(nèi)存:
- 靜態(tài)內(nèi)存:局部static對象搞动,類static數(shù)據(jù)成員,定義在任何函數(shù)外的變量→使用前分配內(nèi)存改橘,程序結(jié)束時銷毀滋尉;
- 局部static對象:令局部變量的聲明周期貫穿函數(shù)調(diào)用及之后的時間,在程序執(zhí)行路徑第一次經(jīng)過對象定義語句時初始化飞主,知道程序終止被銷毀
- 棧內(nèi)存:定義在函數(shù)內(nèi)的非static對象→僅在其定義的程序塊運行時存在狮惜;
- 分配在靜態(tài)或者棧內(nèi)存中的對象由編譯器自動創(chuàng)建和銷毀
- 動態(tài)內(nèi)存:動態(tài)分配,生存期由程序控制→顯示創(chuàng)建碌识,顯示銷毀碾篡。
- 靜態(tài)內(nèi)存:局部static對象搞动,類static數(shù)據(jù)成員,定義在任何函數(shù)外的變量→使用前分配內(nèi)存改橘,程序結(jié)束時銷毀滋尉;
- 動態(tài)內(nèi)存:
- new創(chuàng)建,delete銷毀→確保正確釋放內(nèi)存困難筏餐。
- (c++11)智能指針:shared_ptr 允許多個指針指向同一對象开泽,unique_ptr 不允許...., weak_ptr 伴隨類魁瞪?穆律,弱引用?导俘,指向shared_ptr指向的對象峦耘。→memory頭文件中
- 使用動態(tài)生存期的資源:
- 程序不知道自己需要多少對象旅薄;
- 程序不知道所需對象的準確類型辅髓;
- 程序需要在多個對象間共享數(shù)據(jù)。
零少梁、術語表
一洛口、動態(tài)內(nèi)存和智能指針
- shared_ptr類
模板類→創(chuàng)建:shared_ptr<string> p1; shared_ptr<list<int>> p2;
-
初始化:
- 默認初始化→保存空指針;
- 其他方式凯沪?(12.1.3)
操作:
shared_ptr和unique_ptr共有:shared_ptr<T> sp第焰;p;*p妨马;p->mem樟遣;p.get()?身笤; swap(p,q);p.swap(q)
shared_ptr 獨有:make_shared<T> (args)葵陵;shared_ptr<T> p(q)液荸;p=q;p.unique()脱篙;p.use _count()-
make_shared函數(shù)
- 最安全的分配和使用動態(tài)內(nèi)存的方法娇钱,memory頭文件伤柄;
- 類似順序容器的emplace成員,用其參數(shù)來構造給定類型的對象文搂;
eg. shared_ptr<int> p1 = make_shared<int>(42);
shared_ptr<string> p2 = make_shared<string>(10,'9'); - 不傳遞參數(shù)時→值初始化适刀;
-
shared_ptr的工作原理:
- 可認為每個shared_ptr都有一個關聯(lián)的計數(shù)器(引用計數(shù));
- 一旦計數(shù)器變?yōu)?煤蹭,會自動釋放所管理的對象→通過析構函數(shù)銷毀笔喉, - shared_ptr的析構函數(shù) 遞減它指向?qū)ο蟮囊糜嫈?shù)/計數(shù)為0時釋放內(nèi)存;
- 計數(shù)器:
- 拷貝→計數(shù)器遞增硝皂;
- 賦值p = q → p指向?qū)ο笥嫈?shù)遞減常挚,q指向?qū)ο笥嫈?shù)遞增;
- 返回p→ 需要向調(diào)用者傳遞一個p的拷貝稽物,計數(shù)遞增奄毡。
- shared_ptr被銷毀,例如一個局部的shared_ptr離開其作用域→計數(shù)器遞減
- 由于在最后一個shared_ptr銷毀前內(nèi)存都不會釋放贝或,所以需要保證shared_ptr在無用之后不再保留吼过;
回顧知識點:
基于const的重載→通過區(qū)分成員函數(shù)是否是const對其重載,分別適用于常量版本和非常量版本的對象咪奖。
initializer_list→6.2.6
- 直接管理內(nèi)存
- 使用new分配和初始化對象:new無法為分配的對象命名盗忱,而是返回一個指向該對象的指針:int *pi = new int;
- 初始化:
- 默認初始化→默認狀況下使用,(內(nèi)置類型或組合類型對象的值未定義赡艰,類類型用默認構造函數(shù))售淡;
- 定義變量時沒有指定初值,則變量被默認初始化慷垮;
- 內(nèi)置類型揖闸,定義于任何函數(shù)體之外被初始化為0,否則不被初始化料身,值是未定義的→建議初始化每一個內(nèi)置類型的變量
- 直接初始化→圓括號汤纸,int *pi = new int(1024), string *s = new string(10,'9');
- 列表初始化 vector<int> *p = new vector<int>{0,1,2,3,4,5}
- 值初始化:→int *p = new int()芹血;
- 內(nèi)置類型贮泞,初始值設為0
- 其余類型,默認初始化
- 默認初始化→默認狀況下使用,(內(nèi)置類型或組合類型對象的值未定義赡艰,類類型用默認構造函數(shù))售淡;
- 可以用new分配const對象:const int *pci = new const int(1024)→該對象必須初始化幔烛。
- 使用delete釋放內(nèi)存:接受一個指向想要釋放對象的指針:delete p啃擦,p必須指向一個動態(tài)分配的對象或空指針!饿悬,動態(tài)分配的const對象不可被改變但可被銷毀令蛉。
- 執(zhí)行兩個動作:銷毀給定指針指向的對象,釋放對應的內(nèi)存。
- 指向動態(tài)對象的指針必需記得在不用時釋放內(nèi)存珠叔,eg蝎宇,當一個指針離開其作用域,它指向的對象什么都不會發(fā)生祷安,如果是一個指向動態(tài)對象的指針姥芥,那么內(nèi)存將不被釋放。
-
new,delete使用常見問題:
- 忘記delete內(nèi)存汇鞭;
- 使用已經(jīng)釋放掉的對象凉唐;
- 同一塊內(nèi)存釋放兩次;
- 空懸指針:指向一塊曾經(jīng)保存數(shù)據(jù)對象虱咧,但現(xiàn)在已經(jīng)無效的內(nèi)存的指針熊榛,如:int *p = new int(43); auto q = p; delete p;→q現(xiàn)在是一個空懸指針腕巡。
shared_ptr和new結(jié)合使用
unique_ptr
weak_ptr