• <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>
            淺談C++中的內(nèi)存管理
            摘要:

            大家都知道變量的生存周期這個(gè)概念,可是有的時(shí)候命名生存周期已經(jīng)結(jié)束,但是所分配的那塊內(nèi)存空間還是存在的。文章舉了四個(gè)不同的例子,來(lái)說(shuō)明這其中的原因。

            前言:

            前一段時(shí)間在一個(gè)好友的的博客論壇上看到他學(xué)習(xí)C++時(shí)遇到的一小點(diǎn)問(wèn)題,是關(guān)于C++中最基本的內(nèi)存分配方面的。其實(shí)對(duì)于內(nèi)存這東西,除了知道我自己用的是256M的內(nèi)存以外,我也不太清楚他到底里面是怎么工作的。看了大師們的講解,我深有體會(huì),把這些講解整理出來(lái),為所有C++的newbie們共勉!

            正文:

            事情是因?yàn)檫@樣一小段程序而來(lái)的。

            int main()
            {
              int i=10;
              int *j=&i;
              if(!0)
              {
                int l=20;
                int *k=&l;
                j=k;
                k=0;
              }
              cout<<*j;
              return 0;
            }


            不用編譯器,大家想想執(zhí)行過(guò)之后應(yīng)該打印什么結(jié)果?我想大家的第一反應(yīng)應(yīng)該是打印出一個(gè)不確定的數(shù)。理由是在if語(yǔ)句里,我們定義了k這個(gè)變量,在if執(zhí)行結(jié)束之后,這個(gè)變量k所占據(jù)的內(nèi)存是被系統(tǒng)收回的,于是也就造成了變量j所指的結(jié)果非常不確定。當(dāng)然,如果編譯并且執(zhí)行過(guò)后,我們發(fā)現(xiàn)事情并不是像我們想象的那樣,程序最終的打印結(jié)果是20,并不是我們期待的一個(gè)不確定的數(shù)。下面就讓我們分析一下原因吧!

            我們用debug的方式來(lái)一步一步的分析,在watch的窗口下輸入里面所有的變量。

            int i=10;  //i is 10 and &i is 0x0012ff7c
            int *j=&i; //*j is 10 and &j is 0x0012ff7c
                  //顯然可以看出此時(shí)兩個(gè)變量指的是同一地址
            if(!0)
            {
              int l=20; //l is 20 and &l is 0x0012ff74

              /*地址0x0012ff7c—0x0012ff75被占據(jù)。要說(shuō)明的是,
              這個(gè)數(shù)值很有可能因?yàn)殡娔X硬件的不同而不同。*/

              int *k=&l; //*k is 20 and &k is 0x0012ff74

              //變量k與l指向同一地址。

              j=k;  //j is 0x0012ff74 and *j is 20

              /*指針間的賦值,這個(gè)語(yǔ)句的意思是把k指向的地址負(fù)值給j。
              此時(shí)這兩個(gè)變量指向的是同一個(gè)地址,都是0x0012ff74,而那
              塊地址存放的是20,所以也就有*j是20的原因。*/
            }

            cout<<*j; //*j is 20 and j is 0x0012ff74

            /*此時(shí)同時(shí)可以看到k的地址是0x00000000,說(shuō)明k這個(gè)變量
            已經(jīng)被自動(dòng)銷毀,所以地址指零。但是j所指的并不是k,而
            是k所指的那段地址0x0012ff74,而由于此時(shí)j的生存周期還
            沒(méi)有結(jié)束(j是在if意外定義的),所以j指向的這塊地址并
            沒(méi)有被收回,也就保存下來(lái)20這個(gè)數(shù)了。*/


            至此,我們分析完了程序的全過(guò)程的內(nèi)存分配情況,最終結(jié)果是這樣的。(圖1)
            無(wú)標(biāo)題.JPG

            我們同時(shí)也可以在Memory里面看看這個(gè)地址的具體內(nèi)容。我們可以看到是14,這是十六進(jìn)制的數(shù),化成十進(jìn)制,正好是20。(圖2)
            無(wú)標(biāo)題2.JPG

            現(xiàn)在大家應(yīng)該對(duì)上面那個(gè)程序的執(zhí)行過(guò)程有一個(gè)大概地了解了吧!不過(guò)這個(gè)還不是我們想要得到的結(jié)果,我們需要的是打印一個(gè)不確定的結(jié)果。有了以上的分析,我們開(kāi)始新的程序,讓他打印出我們想要的東西。

            對(duì)于上面的程序,我們需要改動(dòng)的是令變量j指向一個(gè)地址被釋放的位置。于是就有了下面的程序。

            int * foo()
            {
              int l=20;
              return &l;
            }

            int main()
            {
              int i=10;
              int *j=&i;
              j = foo();
              cout<<*j;
              return 0;
            }

            編譯器很“聰明”,編譯后會(huì)給出一個(gè)警告。原話是“returning address of local variable or temporary”,指向的是上面程序的第四行,也就是return &l;這條語(yǔ)句。那句英文的意思也不用我再多解釋了,相信大家都能看得明白。

            執(zhí)行的結(jié)果,在debug下,是20;在release下,結(jié)果是4198795。顯然那部分內(nèi)存被釋放掉了。這是因?yàn)樵赿ebug的程序里面,執(zhí)行完函數(shù)foo,并沒(méi)有立即釋放掉l的那個(gè)地址(目前我不清楚這句話說(shuō)得是否精確)。在這個(gè)程序的release版本中,顯然程序釋放了那部分的地址,所以指向了一個(gè)不確定的數(shù)。

            這里還要說(shuō)一件事情,就是在第一個(gè)程序當(dāng)中,無(wú)論是debug版本還是release版本。執(zhí)行完那個(gè)if語(yǔ)句以后,系統(tǒng)都是不會(huì)真正的把l清除掉,l只是k的一個(gè)別名。上面的程序是這樣寫的,用了*j=&i這樣一句負(fù)值語(yǔ)句,而別名在MSDN中的解釋與引用是相同的,所以也可以這樣理解,int i=10; int &j=i;與上面的相同。不要去想上面這些程序了,大家再看看下面這個(gè)。

            void f1( int *& j)
            {
              int l=20;
              int *k=&l;
              j=k;
              k=0;
            }

            void any_function_use_local_variables()
            {
              int a,b,c;
              a=b=c=100;
            }

            int main()
            {
              int i=10;
              int *j=&i;
              f1(j);
              cout<<*j;
              any_function_use_local_variables();
              cout<<*j;
              return 0;
            }


            請(qǐng)大家自己編譯、執(zhí)行,看看結(jié)果是什么,然后結(jié)合上面的兩個(gè)例子,想想是為什么。下面再給大家一個(gè)小例子,可能會(huì)有助于理解內(nèi)存的概念。

            程序的過(guò)程是試圖去增加i,使之超過(guò)最大的整數(shù)。有一種情況是這個(gè)值被“卷回來(lái)”變成一個(gè)負(fù)數(shù),在我的機(jī)器上程序的打印結(jié)果是-2147483648,這個(gè)結(jié)果可能因?yàn)橛布牟煌煌?BR>

            int main()
            {
              int i=1;
              while(0<i) i++;
              cout<<i;
              return 0;
            }

            結(jié)束:

            其實(shí)我對(duì)于內(nèi)存的理解也是極為有限的。討論這個(gè)問(wèn)題的原帖子在這里。里面回答問(wèn)題的全都是Microsoft MVP或者是準(zhǔn)MVP,我也是從那里學(xué)習(xí)過(guò)來(lái)的。希望大家能從我的這篇文章中受益。這樣,也就達(dá)到了我寫文章的目的。:P

            了解更多詳情,參與討論,請(qǐng)進(jìn)入GBUNIX論壇

            http://www.gbunix.com/bbs/forums.html


            Posted on 2005-11-11 12:15 艾凡赫 閱讀(344) 評(píng)論(0)  編輯 收藏 引用 所屬分類: C++
            伊人久久大香线焦综合四虎| A级毛片无码久久精品免费| 日韩久久无码免费毛片软件| 波多野结衣久久一区二区| 日日噜噜夜夜狠狠久久丁香五月| 久久亚洲国产午夜精品理论片| 久久精品中文字幕一区| 国内精品伊人久久久久AV影院| 国产999精品久久久久久| 一本色道久久99一综合| 久久精品亚洲福利| 精品免费久久久久久久| 久久久这里有精品| 国产激情久久久久影院小草| 人妻少妇久久中文字幕一区二区 | 精品无码人妻久久久久久| 久久人人爽人人人人片av| 久久久久婷婷| 久久久人妻精品无码一区| 精品国产福利久久久| 久久超乳爆乳中文字幕| 久久精品人妻中文系列| 老司机午夜网站国内精品久久久久久久久| 亚洲国产精品无码久久一线| 亚洲欧美国产精品专区久久| 伊人色综合久久天天| AV无码久久久久不卡网站下载| 97精品国产97久久久久久免费| 欧美午夜A∨大片久久| 久久国产成人精品国产成人亚洲| 久久国产精品久久久| 国产精品久久久久aaaa| 91久久婷婷国产综合精品青草| 精品久久人妻av中文字幕| 久久亚洲精精品中文字幕| 国内精品久久久久久99蜜桃| 久久亚洲精精品中文字幕| 国产精品九九九久久九九| 999久久久国产精品| 人妻少妇精品久久| 欧美喷潮久久久XXXXx|