青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆-250  評(píng)論-20  文章-55  trackbacks-0
4 、指針參數(shù)是如何傳遞內(nèi)存的?
?
如果函數(shù)的參數(shù)是一個(gè)指針,不要指望用該指針去申請(qǐng)動(dòng)態(tài)內(nèi)存。示例7-4-1中,Test函數(shù)的語句GetMemory(str, 200)并沒有使str獲得期望的內(nèi)存,str依舊是NULL,為什么?
void GetMemory(char *p, int num)
{
 p = (char *)malloc(sizeof(char) * num);
}
void Test(void)
{
 char *str = NULL;
 GetMemory(str, 100); // str 仍然為 NULL
 strcpy(str, "hello"); // 運(yùn)行錯(cuò)誤
}
      示例4.1 試圖用指針參數(shù)申請(qǐng)動(dòng)態(tài)內(nèi)存
?
毛病出在函數(shù)GetMemory中。編譯器總是要為函數(shù)的每個(gè)參數(shù)制作臨時(shí)副本,指針參數(shù)p的副本是 _p,編譯器使 _p = p。如果函數(shù)體內(nèi)的程序修改了_p的內(nèi)容,就導(dǎo)致參數(shù)p的內(nèi)容作相應(yīng)的修改。這就是指針可以用作輸出參數(shù)的原因。在本例中,_p申請(qǐng)了新的內(nèi)存,只是把 _p所指的內(nèi)存地址改變了,但是p絲毫未變。所以函數(shù)GetMemory并不能輸出任何東西。事實(shí)上,每執(zhí)行一次GetMemory就會(huì)泄露一塊內(nèi)存,因?yàn)闆]有用free釋放內(nèi)存。

  如果非得要用指針參數(shù)去申請(qǐng)內(nèi)存,那么應(yīng)該改用“指向指針的指針”,見示例4.2。
void GetMemory2(char **p, int num)
{
 *p = (char *)malloc(sizeof(char) * num);
}
void Test2(void)
{
 char *str = NULL;
 GetMemory2(&str, 100); // 注意參數(shù)是 &str,而不是str
 strcpy(str, "hello");
 cout<< str << endl;
 free(str);
}
      示例4.2用指向指針的指針申請(qǐng)動(dòng)態(tài)內(nèi)存
?
?
由于“指向指針的指針”這個(gè)概念不容易理解,我們可以用函數(shù)返回值來傳遞動(dòng)態(tài)內(nèi)存。這種方法更加簡單,見示例4.3。

char *GetMemory3(int num)
{
 char *p = (char *)malloc(sizeof(char) * num);
 return p;
}
void Test3(void)
{
 char *str = NULL;
 str = GetMemory3(100);
 strcpy(str, "hello");
 cout<< str << endl;
 free(str);
}
       示例4.3 用函數(shù)返回值來傳遞動(dòng)態(tài)內(nèi)存
?
用函數(shù)返回值來傳遞動(dòng)態(tài)內(nèi)存這種方法雖然好用,但是常常有人把return語句用錯(cuò)了。這里強(qiáng)調(diào)不要用return語句返回指向“棧內(nèi)存”的指針,因?yàn)樵搩?nèi)存在函數(shù)結(jié)束時(shí)自動(dòng)消亡,見示例4.4。
?
char *GetString(void)
{
 char p[] = "hello world";
 return p; // 編譯器將提出警告
}
void Test4(void)
{
 char *str = NULL;
 str = GetString(); // str 的內(nèi)容是垃圾
 cout<< str << endl;
}
      示例4.4 return語句返回指向“棧內(nèi)存”的指針
?
?
用調(diào)試器逐步跟蹤Test4,發(fā)現(xiàn)執(zhí)行str = GetString語句后str不再是NULL指針,但是str的內(nèi)容不是“hello world”而是垃圾。
如果把示例4.4改寫成示例4.5,會(huì)怎么樣?

char *GetString2(void)
{
 char *p = "hello world";
 return p;
}
void Test5(void)
{
 char *str = NULL;
 str = GetString2();
 cout<< str << endl;
}
     示例4.5 return語句返回常量字符串



  函數(shù)Test5運(yùn)行雖然不會(huì)出錯(cuò),但是函數(shù)GetString2的設(shè)計(jì)概念卻是錯(cuò)誤的。因?yàn)镚etString2內(nèi)的“hello world”是常量字符串,位于靜態(tài)存儲(chǔ)區(qū),它在程序生命期內(nèi)恒定不變。無論什么時(shí)候調(diào)用GetString2,它返回的始終是同一個(gè)“只讀”的內(nèi)存塊。
?
5 、杜絕 野指針
?
“野指針”不是NULL指針,是指向“垃圾”內(nèi)存的指針。人們一般不會(huì)錯(cuò)用NULL指針,因?yàn)橛胕f語句很容易判斷。但是“野指針”是很危險(xiǎn)的,if語句對(duì)它不起作用。 “野指針”的成因主要有兩種:

 ?。?)指針變量沒有被初始化。任何指針變量剛被創(chuàng)建時(shí)不會(huì)自動(dòng)成為NULL指針,它的缺省值是隨機(jī)的,它會(huì)亂指一氣。所以,指針變量在創(chuàng)建的同時(shí)應(yīng)當(dāng)被初始化,要么將指針設(shè)置為NULL,要么讓它指向合法的內(nèi)存。例如


char *p = NULL;
char *str = (char *) malloc(100);


  (2)指針p被free或者delete之后,沒有置為NULL,讓人誤以為p是個(gè)合法的指針。

 ?。?)指針操作超越了變量的作用范圍。這種情況讓人防不勝防,示例程序如下:

class A
{
 public:
  void Func(void){ cout << “Func of class A” << endl; }
};
void Test(void)
{
 A *p;
 {
  A a;
  p = &a; // 注意 a 的生命期
 }
 p->Func(); // p是“野指針”
}



  函數(shù)Test在執(zhí)行語句p->Func()時(shí),對(duì)象a已經(jīng)消失,而p是指向a的,所以p就成了“野指針”。但奇怪的是我運(yùn)行這個(gè)程序時(shí)居然沒有出錯(cuò),這可能與編譯器有關(guān)。

6、有了malloc/free為什么還要new/delete

  malloc與free是C++/C語言的標(biāo)準(zhǔn)庫函數(shù),new/delete是C++的運(yùn)算符。它們都可用于申請(qǐng)動(dòng)態(tài)內(nèi)存和釋放內(nèi)存。

  對(duì)于非內(nèi)部數(shù)據(jù)類型的對(duì)象而言,光用maloc/free無法滿足動(dòng)態(tài)對(duì)象的要求。對(duì)象在創(chuàng)建的同時(shí)要自動(dòng)執(zhí)行構(gòu)造函數(shù),對(duì)象在消亡之前要自動(dòng)執(zhí)行析構(gòu)函數(shù)。由于malloc/free是庫函數(shù)而不是運(yùn)算符,不在編譯器控制權(quán)限之內(nèi),不能夠把執(zhí)行構(gòu)造函數(shù)和析構(gòu)函數(shù)的任務(wù)強(qiáng)加于malloc/free。

  因此C++語言需要一個(gè)能完成動(dòng)態(tài)內(nèi)存分配和初始化工作的運(yùn)算符new,以及一個(gè)能完成清理與釋放內(nèi)存工作的運(yùn)算符delete。注意 new/delete不是庫函數(shù)。我們先看一看malloc/free和new/delete如何實(shí)現(xiàn)對(duì)象的動(dòng)態(tài)內(nèi)存管理,見示例6。


class Obj
{
 public :
  Obj(void){ cout << “Initialization” << endl; }
  ~Obj(void){ cout << “Destroy” << endl; }
  void Initialize(void){ cout << “Initialization” << endl; }
  void Destroy(void){ cout << “Destroy” << endl; }
};
void UseMallocFree(void)
{
 Obj *a = (obj *)malloc(sizeof(obj)); // 申請(qǐng)動(dòng)態(tài)內(nèi)存
 a->Initialize(); // 初始化
 //…
 a->Destroy(); // 清除工作
 free(a); // 釋放內(nèi)存
}
void UseNewDelete(void)
{
 Obj *a = new Obj; // 申請(qǐng)動(dòng)態(tài)內(nèi)存并且初始化
 //…
 delete a; // 清除并且釋放內(nèi)存
}
     示例6 用malloc/free和new/delete如何實(shí)現(xiàn)對(duì)象的動(dòng)態(tài)內(nèi)存管理


  類Obj的函數(shù)Initialize模擬了構(gòu)造函數(shù)的功能,函數(shù)Destroy模擬了析構(gòu)函數(shù)的功能。函數(shù)UseMallocFree中,由于 malloc/free不能執(zhí)行構(gòu)造函數(shù)與析構(gòu)函數(shù),必須調(diào)用成員函數(shù)Initialize和Destroy來完成初始化與清除工作。函數(shù) UseNewDelete則簡單得多。

  所以我們不要企圖用malloc/free來完成動(dòng)態(tài)對(duì)象的內(nèi)存管理,應(yīng)該用new/delete。由于內(nèi)部數(shù)據(jù)類型的“對(duì)象”沒有構(gòu)造與析構(gòu)的過程,對(duì)它們而言malloc/free和new/delete是等價(jià)的。

  既然new/delete的功能完全覆蓋了malloc/free,為什么C++不把malloc/free淘汰出局呢?這是因?yàn)镃++程序經(jīng)常要調(diào)用C函數(shù),而C程序只能用malloc/free管理動(dòng)態(tài)內(nèi)存。
如果用free釋放“new創(chuàng)建的動(dòng)態(tài)對(duì)象”,那么該對(duì)象因無法執(zhí)行析構(gòu)函數(shù)而可能導(dǎo)致程序出錯(cuò)。如果用delete釋放“malloc申請(qǐng)的動(dòng)態(tài)內(nèi)存”,理論上講程序不會(huì)出錯(cuò),但是該程序的可讀性很差。所以new/delete必須配對(duì)使用,malloc/free也一樣。
posted on 2007-02-24 23:43 jay 閱讀(2341) 評(píng)論(1)  編輯 收藏 引用 所屬分類: 內(nèi)存管理

評(píng)論:
# re: C++內(nèi)存管理詳解(二) 2012-05-10 10:59 | igouz
好像在哪本書上看過。謝謝分享。  回復(fù)  更多評(píng)論
  

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


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            亚洲视频在线观看| 亚洲视频一区在线观看| 欧美成人三级在线| 欧美第一黄网免费网站| 欧美成人免费全部观看天天性色| 免费在线观看一区二区| 欧美激情国产精品| 国产精品国产自产拍高清av| 国产欧美日韩不卡| 亚洲国内高清视频| 亚洲一区三区电影在线观看| 欧美在线亚洲| 欧美激情一区二区三区四区| 亚洲精品亚洲人成人网| 亚洲视频axxx| 久久久精品国产一区二区三区| 另类尿喷潮videofree| 欧美va亚洲va国产综合| 欧美视频在线免费看| 狠狠噜噜久久| 亚洲午夜激情在线| 老司机亚洲精品| 一本色道婷婷久久欧美| 久久成人免费网| 99在线观看免费视频精品观看| 国产精品99久久久久久人| 亚洲高清av在线| 亚洲精品久久久久久久久久久久久| 99精品视频一区二区三区| 亚洲一区成人| 麻豆久久精品| 国产女人精品视频| 亚洲日本一区二区三区| 亚洲欧美日韩在线观看a三区| 久久久欧美精品| 亚洲看片网站| 久久人人精品| 国产美女精品视频免费观看| 亚洲日本一区二区三区| 久久精品免费看| 99国产精品久久久| 免费人成网站在线观看欧美高清| 国产精品一区免费观看| 99精品久久免费看蜜臀剧情介绍| 欧美影片第一页| 亚洲欧洲另类| 久久精品国产一区二区电影| 欧美无砖砖区免费| 亚洲精品社区| 欧美激情视频免费观看| 久久av一区二区三区漫画| 国产精品免费视频观看| 亚洲婷婷在线| 一区二区高清在线观看| 欧美激情精品久久久久久| 亚洲国产精品久久久久| 老司机凹凸av亚洲导航| 久久国产高清| 一区二区三区在线免费视频| 久久成人免费电影| 亚洲欧美日韩综合国产aⅴ | 99亚洲视频| 欧美精品色综合| 99av国产精品欲麻豆| 欧美激情中文不卡| 欧美国产精品劲爆| 日韩一级精品| 一本色道久久99精品综合| 欧美日韩综合一区| 亚洲在线一区二区| 一区二区三区欧美亚洲| 国产精品免费一区豆花| 久久精品免费看| 久久久久国产精品一区二区| 一区在线观看| 亚洲福利小视频| 欧美日韩中文在线观看| 先锋影音久久久| 久久精彩视频| 亚洲精品欧美在线| 在线观看一区二区精品视频| 99国产精品久久久| 一本色道久久综合亚洲精品小说| 欧美视频免费看| 久久成人免费日本黄色| 久久亚洲精品网站| 99re热这里只有精品免费视频| 99精品国产一区二区青青牛奶 | 欧美日韩在线综合| 久久av在线看| 玖玖在线精品| 中文有码久久| 久久噜噜噜精品国产亚洲综合| 亚洲精品乱码久久久久久按摩观 | 免费h精品视频在线播放| 日韩视频欧美视频| 午夜一区二区三视频在线观看 | 美女成人午夜| 欧美人成网站| 久久免费黄色| 国产精品theporn| 欧美激情精品久久久六区热门| 欧美视频在线免费看| 欧美 日韩 国产精品免费观看| 欧美日韩中文在线观看| 欧美成人精品福利| 国产欧美一区二区精品性 | 久久精品视频免费观看| 欧美成人免费观看| 久久一区欧美| 国产精品日本欧美一区二区三区| 欧美成人免费全部| 国产视频一区在线观看| 日韩亚洲在线| 日韩一级裸体免费视频| 久久久久综合网| 午夜欧美大片免费观看 | 欧美偷拍一区二区| 欧美岛国激情| 国产在线视频不卡二| 亚洲午夜精品久久久久久app| 亚洲人成网站999久久久综合| 久久国产精品久久久久久电车| 亚洲欧美成人网| 欧美日韩国产限制| 亚洲国产综合视频在线观看| 极品av少妇一区二区| 欧美一区二区精品| 欧美一级久久久久久久大片| 欧美午夜精品久久久久久超碰| 亚洲美女福利视频网站| 亚洲三级视频在线观看| 美女视频一区免费观看| 蜜臀av性久久久久蜜臀aⅴ| 国产日本亚洲高清| 香蕉久久国产| 久久久久国产精品一区| 国产九九精品| 一道本一区二区| 欧美精选在线| 久久久久久穴| 韩日欧美一区二区| 久久久www成人免费无遮挡大片| 欧美在线观看一区| 国产婷婷色一区二区三区四区| 亚洲男女自偷自拍| 久久久精品日韩| 一区二区三区在线看| 久久综合激情| 91久久综合亚洲鲁鲁五月天| 一本色道久久综合亚洲精品按摩 | 欧美专区18| 狠狠综合久久av一区二区小说| 久久婷婷激情| 亚洲日本成人| 午夜精品久久久久久99热| 国产偷久久久精品专区| 久久青青草综合| 亚洲另类自拍| 欧美一区二区高清| 在线成人性视频| 欧美精品999| 午夜久久久久久| 欧美激情亚洲综合一区| 亚洲一本视频| 极品少妇一区二区三区| 欧美日韩国产色综合一二三四 | 欧美好骚综合网| 亚洲尤物影院| 伊伊综合在线| 欧美视频在线播放| 久久国产精品亚洲va麻豆| 亚洲欧洲精品天堂一级| 午夜精品福利视频| 亚洲福利视频网| 国产精品爽黄69| 免费观看日韩| 午夜精品久久久久久久久| 欧美成人第一页| 欧美亚洲日本国产| 最新日韩欧美| 国产日韩一区二区三区在线| 欧美国产精品劲爆| 欧美一激情一区二区三区| 亚洲日韩欧美视频一区| 久久免费视频在线观看| 亚洲一区欧美二区| 亚洲精品三级| 亚洲成色777777女色窝| 国产精一区二区三区| 欧美色大人视频| 欧美国产在线观看| 毛片基地黄久久久久久天堂| 亚洲欧美日韩国产精品| 亚洲美女黄网| 亚洲国产精品一区制服丝袜| 久久综合网络一区二区| 欧美一区2区三区4区公司二百| 99在线精品视频在线观看| 亚洲国产精品女人久久久|