• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆 - 55  文章 - 15  trackbacks - 0
            <2012年4月>
            25262728293031
            1234567
            891011121314
            15161718192021
            22232425262728
            293012345

            常用鏈接

            留言簿

            隨筆分類

            隨筆檔案

            搜索

            •  

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

                  最近在重溫c++基礎(chǔ)知識(shí),反正閑著也是沒(méi)事干,以前只聽(tīng)說(shuō)過(guò)這本書(shū),但是從來(lái)沒(méi)看過(guò)。畢業(yè)那會(huì)看的是面向?qū)ο缶幊蹋彩菄?guó)外的某個(gè)牛人寫(xiě)的,但是是機(jī)械出版社出版的,讀起來(lái)比較順暢,但是里面有些細(xì)節(jié)還是不清楚。這本書(shū)是c++大牛寫(xiě)的,清華大學(xué)出版社翻譯出來(lái),剛開(kāi)始讀的時(shí)候覺(jué)得翻譯挺別扭的,但是自己去看原文的時(shí)候,又礙于語(yǔ)言學(xué)的不好,發(fā)現(xiàn)很多翻譯出來(lái)還沒(méi)這本書(shū)好,就先姑且讀之,以后慢慢再看英文原版。
                  讀了這么長(zhǎng)時(shí)間的書(shū)了,第一卷基本上要讀完了,最后四章之前看得比較匆忙,沒(méi)好好理解,現(xiàn)在又重新翻了一遍,很多東西跟我原來(lái)想的完全不一樣,而且這本書(shū)讀了之后可以讓人知道為什么要這樣做,從根本上剖析了做這件事的理由,我覺(jué)得讀了之后挺有益的,就先把讀書(shū)筆記貼出來(lái)。
                  
                  今天分享一下new 和 delete兩個(gè)操作符,面試的時(shí)候面試官很喜歡問(wèn),new 和 malloc有什么區(qū)別?當(dāng)初只是知道new最重要的是要調(diào)用構(gòu)造函數(shù),而不知道為什么非要調(diào)用構(gòu)造函數(shù)。
                  先來(lái)看一下如果沒(méi)有new的話,用malloc()怎么在內(nèi)存中分配一塊區(qū)域給一個(gè)類對(duì)象,分配了之后,接下來(lái)應(yīng)該怎么辦。
                  
                  下面是書(shū)中的一個(gè)例子,解答了上述的問(wèn)題:
            class Obj
            {
               int i,j,k;
               enum{ sz = 100 };
               char buf[sz];
            public:
               void initialize()
              {
                 cout << "initializing Obj" << endl;
                 i = j = k;
                 memset(buf, 0 , sz);
               }
               void destroy()const
               {
                 cout<< "destroying Obj" << endl;
                }

            };

            int main()
            {
              Obj* obj = (Obj*)malloc(sizeof(Obj));
              assert(obj != null);
              obj->initialize();
              obj->destroy();
              return 0;
            }

                  我們知道,在c++中,編譯器一定要初始化一個(gè)類對(duì)象之后才能對(duì)其進(jìn)行操作,使用malloc動(dòng)態(tài)分配內(nèi)存給對(duì)象之后,還要記得一定要初始化它,不然,這個(gè)對(duì)象就沒(méi)辦法用,而且很多人只關(guān)注類的功能,而不往往會(huì)忘掉初始化,這是bug的一個(gè)重要來(lái)源。所以c++想把分配內(nèi)存和初始化這兩份工作一塊讓編譯器處理了,不用我們程序員惦記著。

                  所以new的作用就是,先為這個(gè)對(duì)象分配一塊足夠容納這個(gè)對(duì)象的內(nèi)存,然后調(diào)用其構(gòu)造函數(shù),初始化這塊內(nèi)存區(qū)域(注意分配內(nèi)存和初始化的順序,這對(duì)我們自理解重載new操作符有幫助)。delete的作用就是,先調(diào)用析構(gòu)函數(shù)將內(nèi)存中的參數(shù)清理掉(我理解是:指針清零,其他變量不管), 然后釋放這塊內(nèi)存。

                  這里說(shuō)一下前幾天看的網(wǎng)易公開(kāi)課中的《編程范式》里面講的,其實(shí)我們分配堆上的內(nèi)存的時(shí)候,哪塊內(nèi)存被分配了,哪塊沒(méi)被分配是記錄在一塊區(qū)域里面的,未被分配的空間都是鏈?zhǔn)竭B接起來(lái)的,被分配的空間也是鏈?zhǔn)竭B接起來(lái)的。第一塊未被分配的空間最后四個(gè)字節(jié)指向了下一個(gè)未被分配的空間的地址,然后依次指向后面的未被分配的空間地址。被分配的空間亦是如此。那么,當(dāng)我們調(diào)用new的時(shí)候,申請(qǐng)的這塊內(nèi)存的首地址就被寫(xiě)到前面一個(gè)的最后四個(gè)字節(jié)里面,說(shuō)明這些空間是被占用的,不能再被分配了。當(dāng)我們調(diào)用delete的時(shí)候,這塊內(nèi)存的首地址就會(huì)被寫(xiě)到未分配的字節(jié)中去。如果我們一塊堆內(nèi)存已經(jīng)沒(méi)有用了,但是沒(méi)有釋放掉,那么它的地址不會(huì)被寫(xiě)到未使用字節(jié)中去,那么你永遠(yuǎn)也用不了這塊內(nèi)存,這就是內(nèi)存泄漏。

                  那如果我們重載new和delete操作符的時(shí)候,我們不可能顯示地調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù),那我們?cè)趺磥?lái)重載呢?答案是,我們只負(fù)責(zé)分配內(nèi)存的規(guī)則,調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù)是編譯器的事情。
                  如果我們用全局函數(shù)來(lái)重載new的話,那么原來(lái)的new就沒(méi)用了,就完完全全被我們的new覆蓋了。如果用成員函數(shù)來(lái)做的話,new只針對(duì)那個(gè)類。
                  new操作符會(huì)接受一個(gè)size_t類型的參數(shù),標(biāo)志著要分配的內(nèi)存的大小,這個(gè)參數(shù)是編譯器給我們的。編譯器會(huì)針對(duì)這個(gè)類型判斷該分配多少內(nèi)存。new操作符的返回值是個(gè)void*,因?yàn)槲覀冏龅闹皇且峙湟粔K內(nèi)存,這塊內(nèi)存還沒(méi)被初始化,所以返回值不是指向一個(gè)類的指針。
                  delete操作符接受一個(gè)指向new操作符分配的內(nèi)存的void*指針,之所以是void*, 而不是類型的指針,是因?yàn)槲覀兊膁elete是在析構(gòu)函數(shù)調(diào)用完之后才開(kāi)始回收空間的。所以我說(shuō)要記住順序啊。
                   好了,來(lái)點(diǎn)代碼說(shuō)說(shuō)重載是怎么進(jìn)行的吧。
            #include <cstdlib> // malloc(), free()
            #include <cstdio> // puts() , printf()
            using namespace std;

            voidoperator new( size_t sz)

              printf("operator new %d Bytes\n", sz);
              void* m = malloc(sz);
              if(!m) puts("out of memory");
              return m;
            }

            void operator delete(void* m)
            {
              puts("operator delete");
              free(m);
            }

            class S
            {
              int i[100];
            public:
              S(){ puts("S::S()");}
              ~S(){ puts("S::~S()");}
            };


            int main()
            {
              int* p = new int(47);
              delete p;
              S* s = new S;
              delete s;
              S* sa = new S[3];// 這里我一直以為會(huì)new 3次,調(diào)用3次構(gòu)造函數(shù)。但實(shí)際上是new 1次,
                                      //  分配1204個(gè)字節(jié),然后三次構(gòu)造函數(shù),多余的4個(gè)字節(jié)存放包含的對(duì)象的數(shù)量信息
              delete sa;          //   這里同樣的,調(diào)用三次析構(gòu)函數(shù),delete操作符調(diào)用一次。
              return 0;
            }
                  注意:構(gòu)造函數(shù)總是在new返回之后調(diào)用,如果new失敗的話,構(gòu)造函數(shù)不會(huì)被調(diào)用,且返回值是0。

                  另外需要注意的是,void*指針最好不能用delete釋放,編了一下程序
                  void* a = new Obj(2);
                  delete a;
                  這段代碼編譯是成功的,但是運(yùn)行時(shí),既沒(méi)有調(diào)用構(gòu)造函數(shù),也沒(méi)有調(diào)用析構(gòu)函數(shù),而且程序出現(xiàn)假死現(xiàn)象。我分析原因是,當(dāng)編譯器看到第一行代碼的時(shí)候,知道我只是要分配一個(gè)Obj這么大的一塊內(nèi)存空間,因?yàn)槭莢oid* ,所以我也不必為它初始化。在delete的時(shí)候,既然我不知道你這塊內(nèi)存中放的是什么類型的對(duì)象,那我就不知道應(yīng)該調(diào)用哪個(gè)析構(gòu)函數(shù)。情理上這么分析是合情合理的。
                  
                  另外我學(xué)到的另一點(diǎn)是,重載new[]和重載new操作符原理上是一樣的,它們接收的都是一個(gè)size_t的參數(shù),來(lái)標(biāo)識(shí)分配多少空間。delete[]與delete也基本相同。

                 大概就是這么多,在堆上分配最大的好處是可以被程序員自己控制,有些時(shí)候,在棧中分配內(nèi)存不能滿足我們的要求,就必須在堆上分配。另外,初始化是c++必須要保證的東西,非常重要。
                

                 最后,哪位大神能告訴我怎么排版?博客園自帶的排版功能我怎么不太會(huì)用呢。。。囧








            1
            posted on 2012-04-20 21:07 Dino-Tech 閱讀(224) 評(píng)論(0)  編輯 收藏 引用

            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            中文字幕久久波多野结衣av| 久久婷婷激情综合色综合俺也去| 99久久精品国产高清一区二区 | 久久久久久久久久久久中文字幕 | 一本色道久久88—综合亚洲精品| 久久久国产精华液| 久久91精品久久91综合| 国产真实乱对白精彩久久| 日韩欧美亚洲国产精品字幕久久久| 久久天天躁夜夜躁狠狠| 久久婷婷国产麻豆91天堂| 人人狠狠综合88综合久久| 国产精品久久波多野结衣| 欧洲国产伦久久久久久久| 久久A级毛片免费观看| 久久综合五月丁香久久激情| 精品久久人妻av中文字幕| 久久免费99精品国产自在现线| 久久精品人人做人人爽97| 欧美久久天天综合香蕉伊| 国产91色综合久久免费分享| 伊人精品久久久久7777| 国产精品永久久久久久久久久| 亚洲精品乱码久久久久久自慰| 久久国产香蕉一区精品| 国内精品久久久久久久97牛牛| 国产精品成人久久久| 亚洲精品国产成人99久久| 久久亚洲精精品中文字幕| 狠狠色丁香久久婷婷综合| 久久亚洲欧洲国产综合| 久久久久人妻精品一区| 欧美亚洲国产精品久久久久| 久久久久久毛片免费看| 久久天天躁狠狠躁夜夜av浪潮| 国产∨亚洲V天堂无码久久久| 一本一本久久A久久综合精品 | 三级片免费观看久久| 亚洲狠狠久久综合一区77777| 国内精品人妻无码久久久影院 | 综合久久国产九一剧情麻豆|