第3篇-C/C++ 類和內(nèi)存分配(中)

我們已經(jīng)從前面一篇《第3篇-C/C++ 類和內(nèi)存分配(前)》的一些詳細(xì)例子了解到new操作符的基本用法。

那么,我們現(xiàn)在需要知道在new操作符的底層旬盯,C++編譯器到底做了些什么宝与?首先,new操作符的實(shí)質(zhì)就是一個(gè)函數(shù),但這個(gè)函數(shù)比較特殊,它帶有operator關(guān)鍵字,C++編譯器會對他們做特殊處理礼仗。

new operator函數(shù)原型

void* operator new(size_t size);

因此,我們知道new操作符會返回一個(gè)void指針,void指針是什么虐急?就是萬能指針,在C/C++世界中,你可以理解為面向?qū)ο?/strong>的“造物主”,只要給定一個(gè)無符號大于0的整數(shù),C/C++用該數(shù)據(jù)塊尺寸解析為不同數(shù)據(jù)類型比庄。這就是C/C++中,面向?qū)ο蟮谋驹础D敲磸腃/C++中衍生出來的其他高層語言的琳瑯滿目的面相對象技術(shù)研乒,追根溯源也是void*指針和對應(yīng)的數(shù)據(jù)尺寸汹忠。只不過他們虛擬機(jī)或者編譯器隱藏了這些更底層的操作而已。

備注:標(biāo)準(zhǔn)庫中帶有operator關(guān)鍵字的函數(shù),我們叫做operator函數(shù)雹熬。推而廣之,所有常用的操作符例如I/O中常用的“<<”,“>>”,“endl”都是operator函數(shù)宽菜。

new的底層操作

我們用前文的示例Student類作為一個(gè)示例

typedef struct _student
{
    double score;     //8
    double height;    //8
    char name[6];     //6
    unsigned int sid; //4
    char sex;         //1
} Student;

那么當(dāng)我們new一個(gè)Student的時(shí)候,即以下語句

Student *st=new Student();
  • 第一步:給指定數(shù)據(jù)類型尺寸分配內(nèi)存
    從C++編譯器來說橄唬,它會隱式調(diào)用以下operator函數(shù),并且傳遞了. sizeof(Student)計(jì)算的內(nèi)存塊大小,之前說過是32個(gè)字節(jié)赋焕。

     void* raw=operator new(sizeof(Student));
    

    st指針獲得了Student對象的原始內(nèi)存,也就是st指向原始內(nèi)存的首個(gè)字節(jié)的內(nèi)存地址。

  • 第二步:調(diào)用指定數(shù)據(jù)類型的構(gòu)造函數(shù)并且初始化已分配(堆)內(nèi)存中的對象仰楚。類似下面的偽代碼, 因?yàn)闆]有自定義的構(gòu)造函數(shù),編譯器會使用默認(rèn)構(gòu)造Student,即對象中的數(shù)據(jù)成員都會執(zhí)行默認(rèn)值初始化。

    call Student::Student();
    

    然后犬庇,執(zhí)行類型轉(zhuǎn)換將void指針raw僧界,轉(zhuǎn)換為類型為Student對象的指針類型。

     Student *st=static_cast<Student*>(raw);
    

對象中的數(shù)據(jù)成員

假設(shè)我們的環(huán)境是x86_64,即當(dāng)我們嘗試通過Student的對象指針遍歷對象內(nèi)部的數(shù)據(jù)成員,那么C++編譯器從剛才分配的內(nèi)存空間的首個(gè)字節(jié)的地址st開始讀取,并且每次8個(gè)字節(jié)依次讀取臭挽,加載到寄存器做某些處理捂襟。


堆中Student對象內(nèi)存分布

假設(shè)我們要訪問st的sid屬性,那么C++編譯器做了些什么操作呢?

Student *st=new Student();
...
st->sid

C++編譯器會執(zhí)行如下操作欢峰。

  1. 從st指針的位置向高地址相對偏移24個(gè)字節(jié)葬荷,
  2. 從st+24內(nèi)存地址開始按照8個(gè)字節(jié)為單位加載到寄存器(一般是RAX寄存器)
  3. 在寄存器中向低地址方向shift四個(gè)字節(jié),最終讀取sid四個(gè)字節(jié)的值纽帖。

以下是兩點(diǎn)寄語:

  • 在C++中,盡量不要使用malloc/calloc等C版本的堆內(nèi)存分配API宠漩,一旦你這么做,然后又實(shí)用delete操作符的話,那么就會造成內(nèi)存泄漏懊直。
  • 同理:也不要在C++中使用C版本的free()去釋放由new操作符分配的堆內(nèi)存,否則會造成內(nèi)存泄漏扒吁。

結(jié)語:
當(dāng)我們理解了new的操作符后,可以執(zhí)行更加高級的C++操作室囊,就是重寫C++的void* operator new(size_t)的原型雕崩,但大部分情況下魁索,我們其實(shí)用默認(rèn)版本的new足夠我們?nèi)粘i_發(fā)的需要,反而我們更多需要重寫的是delete操作符和delete[]操作符盼铁。

如果你覺得我的文章對你有所幫助的粗蔚,可以關(guān)注我,并且分享給你的其他圈子饶火,但請著名出處支鸡。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市趁窃,隨后出現(xiàn)的幾起案子牧挣,更是在濱河造成了極大的恐慌,老刑警劉巖醒陆,帶你破解...
    沈念sama閱讀 212,657評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瀑构,死亡現(xiàn)場離奇詭異,居然都是意外死亡刨摩,警方通過查閱死者的電腦和手機(jī)寺晌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,662評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來澡刹,“玉大人呻征,你說我怎么就攤上這事“战剑” “怎么了陆赋?”我有些...
    開封第一講書人閱讀 158,143評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長嚷闭。 經(jīng)常有香客問我攒岛,道長,這世上最難降的妖魔是什么胞锰? 我笑而不...
    開封第一講書人閱讀 56,732評論 1 284
  • 正文 為了忘掉前任灾锯,我火速辦了婚禮,結(jié)果婚禮上嗅榕,老公的妹妹穿的比我還像新娘顺饮。我一直安慰自己,他們只是感情好凌那,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,837評論 6 386
  • 文/花漫 我一把揭開白布兼雄。 她就那樣靜靜地躺著,像睡著了一般案怯。 火紅的嫁衣襯著肌膚如雪君旦。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,036評論 1 291
  • 那天,我揣著相機(jī)與錄音金砍,去河邊找鬼局蚀。 笑死,一個(gè)胖子當(dāng)著我的面吹牛恕稠,可吹牛的內(nèi)容都是我干的琅绅。 我是一名探鬼主播,決...
    沈念sama閱讀 39,126評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼鹅巍,長吁一口氣:“原來是場噩夢啊……” “哼千扶!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起骆捧,我...
    開封第一講書人閱讀 37,868評論 0 268
  • 序言:老撾萬榮一對情侶失蹤澎羞,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后敛苇,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體妆绞,經(jīng)...
    沈念sama閱讀 44,315評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,641評論 2 327
  • 正文 我和宋清朗相戀三年枫攀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了括饶。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,773評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡来涨,死狀恐怖图焰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蹦掐,我是刑警寧澤技羔,帶...
    沈念sama閱讀 34,470評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站笤闯,受9級特大地震影響堕阔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜颗味,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,126評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望牺弹。 院中可真熱鬧浦马,春花似錦、人聲如沸张漂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,859評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽航攒。三九已至磺陡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背币他。 一陣腳步聲響...
    開封第一講書人閱讀 32,095評論 1 267
  • 我被黑心中介騙來泰國打工坞靶, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蝴悉。 一個(gè)月前我還...
    沈念sama閱讀 46,584評論 2 362
  • 正文 我出身青樓彰阴,卻偏偏與公主長得像,于是被迫代替她去往敵國和親拍冠。 傳聞我的和親對象是個(gè)殘疾皇子尿这,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,676評論 2 351