日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

只在堆上或只在栈上定义对象

發(fā)布時(shí)間:2024/9/30 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 只在堆上或只在栈上定义对象 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
轉(zhuǎn)自:http://blog.csdn.net/g5dsk/article/details/4775144 代碼: [cpp]?view plaincopyprint?
  • class?OnlyHeapClass??
  • {??
  • public:??
  • ????OnlyHeapClass()??
  • ????{??
  • ????}??
  • ??
  • ????void?Destroy()??
  • ????{??
  • ????????delete?this;?//?等效于"OnlyHeapClass::~OnlyHeapClass();",?寫??
  • ?????????????????????//?成"OnlyHeapClass::~OnlyHeapClass();"更容易理??
  • ?????????????????????//?解public成員函數(shù)調(diào)用private析構(gòu)函數(shù).??
  • ????}??
  • ??
  • private:??
  • ????~OnlyHeapClass()??
  • ????{??
  • ????}??
  • };??
  • ??
  • int?main()??
  • {??
  • ????OnlyHeapClass?*pInst?=?new?OnlyHeapClass;??
  • ??
  • ????pInst?->Destroy();?//?如果類中沒有定義Destroy()函數(shù),?而在這里用"delete?pInst;"代??
  • ???????????????????????//?替"pInst->Destroy();",?則會(huì)報(bào)錯(cuò).?因?yàn)?#34;delete?pInst;"會(huì)去調(diào)??
  • ???????????????????????//?用類的析構(gòu)函數(shù),?而在類域外調(diào)用類的private成員函數(shù)必然會(huì)報(bào)錯(cuò).??
  • ??
  • ????return?0;??
  • }??
  • 總結(jié):??把析構(gòu)函數(shù)定義為private訪問權(quán)限, 就可以保證只能在堆(heap)上創(chuàng)建(new)一個(gè)新的類對(duì)象. ????
    ??? 原因是C++是一個(gè)靜態(tài)綁定的語言. 在編譯過程中, 所有的非虛函數(shù)調(diào)用都必須分析完成. 即使是虛函數(shù), 也需檢查可訪問性. 因些, 當(dāng)在棧(stack)上生成對(duì)象時(shí), 對(duì)象會(huì)自動(dòng)析構(gòu), 也就說析構(gòu)函數(shù)必須可以訪問. 而堆上生成對(duì)象, 由于析構(gòu)時(shí)機(jī)由程序員控制, 所以不一定需要析構(gòu)函數(shù). 保證了不能在棧上生成對(duì)象后, 需要證明能在堆上生成它. 這里OnlyHeapClass與一般對(duì)象唯一的區(qū)別在于它的析構(gòu)函數(shù)為私有, delete操作會(huì)調(diào)用析構(gòu)函數(shù), 所以不能編譯.

    ??? 那么如何釋放它呢? 答案也很簡(jiǎn)單, 提供一個(gè)成員函數(shù), 完成delete操作. 在成員函數(shù)中, 析構(gòu)函數(shù)是可以訪問的, 當(dāng)然detele操作也是可以編譯通過.
    [cpp]?view plaincopyprint?
  • void?OnlyHeapClass::Destroy()???
  • {???
  • ????delete?this;???
  • }???
  • 析構(gòu)函數(shù)私有化的類的設(shè)計(jì)可以保證只能用new命令在堆(heap)中創(chuàng)建對(duì)象, 只能動(dòng)態(tài)的去創(chuàng)建對(duì)象, 這樣可以自由的控制對(duì)象的生命周期. 但是, 這樣的類需要提供創(chuàng)建和撤銷的公共接口.?

    ??? 另外重載delete, new為私有可以達(dá)到要求對(duì)象創(chuàng)建于棧上的目的, 用placement new也可以創(chuàng)建在棧上.

    [cpp]?view plaincopyprint?
  • /?下面灰色字體系轉(zhuǎn)載幫助理解之用?/??
  • 四.禁止產(chǎn)生堆對(duì)象
    ??? 上面已經(jīng)提到, 你決定禁止產(chǎn)生某種類型的堆對(duì)象, 這時(shí)你可以自己創(chuàng)建一個(gè)資源封裝類, 該類對(duì)象只能在棧中產(chǎn)生, 這樣就能在異常的情況下自動(dòng)釋放封裝的資源.
    ??? 那么怎樣禁止產(chǎn)生堆對(duì)象了? 我們已經(jīng)知道, 產(chǎn)生堆對(duì)象的唯一方法是使用new操作, 如果我們禁止使用new不就行了么. 再進(jìn)一步, new操作執(zhí)行時(shí)會(huì)調(diào)用operator new, 而operator new是可以重載的. 方法有了, 就是使new operator為private, 為了對(duì)稱, 最好將operator delete也重載為private. 現(xiàn)在, 你也許又有疑問了, 難道創(chuàng)建棧對(duì)象不需要調(diào)用new嗎? 是的, 不需要, 因?yàn)閯?chuàng)建棧對(duì)象不需要搜索內(nèi)存, 而是直接調(diào)整堆棧指針, 將對(duì)象壓棧, 而operator new的主要任務(wù)是搜索合適的堆內(nèi)存, 為堆對(duì)象分配空間, 這在上面已經(jīng)提到過了. 好, 讓我們看看下面的示例代碼:??? ? #include <stdlib.h>?? // 需要用到C式內(nèi)存分配函數(shù)???
    ? class Resource ;?? // 代表需要被封裝的資源類???
    ? class NoHashObject???
    ? {???
    ?  private:???
    ?   Resource *ptr ; // 指向被封裝的資源???
    ?   // ...? //其它數(shù)據(jù)成員?
    ??
    ?   void*?? operator?? new(size_t?? size) //非嚴(yán)格實(shí)現(xiàn), 僅作示意之用???
    ?   {???
    ?    return malloc(size);???
    ?   }?
    ??
    ?   void operator delete(void* pp) //非嚴(yán)格實(shí)現(xiàn), 僅作示意之用???
    ?   {???
    ?    free(pp);???
    ?   }
    ??
    ?  public:???
    ?   NoHashObject()???
    ?   {???
    ?    // 此處可以獲得需要封裝的資源, 并讓ptr指針指向該資源???
    ?    ptr = new Resource();???
    ?   }?
    ??
    ?   ~NoHashObject()???
    ?   {???
    ?    delete ptr;?? // 釋放封裝的資源???
    ?   }???
    ? };?????
    ????
    ??? NoHashObject現(xiàn)在就是一個(gè)禁止堆對(duì)象的類了, 如果你寫下如下代碼:????
    ????
    ? NoHashObject* fp = new NoHashObject(); // 編譯期錯(cuò)誤!???
    ? delete fp;?
    ????
    ??? 上面代碼會(huì)產(chǎn)生編譯期錯(cuò)誤. 好了, 現(xiàn)在你已經(jīng)知道了如何設(shè)計(jì)一個(gè)禁止堆對(duì)象的類了, 你也許和我一樣有這樣的疑問, 難道在類NoHashObject的定義不能改變的情況下, 就一定不能產(chǎn)生該類型的堆對(duì)象了嗎? 不, 還是有辦法的, 我稱之為“暴力破解法”. C++是如此地強(qiáng)大, 強(qiáng)大到你可以用它做你想做的任何事情. 這里主要用到的是技巧是指針類型的強(qiáng)制轉(zhuǎn)換.????
    ????
    ? int main()???
    ? {???
    ?  char*?? temp?? =?? new?? char[sizeof(NoHashObject)]?? ;???
    ????
    ?  //強(qiáng)制類型轉(zhuǎn)換, 現(xiàn)在ptr是一個(gè)指向NoHashObject對(duì)象的指針???
    ?  NoHashObject*?? obj_ptr?? =?? (NoHashObject*)temp?? ;???
    ????
    ?  temp?? =?? NULL?? ;?? //防止通過temp指針修改NoHashObject對(duì)象???
    ????
    ?  //再一次強(qiáng)制類型轉(zhuǎn)換, 讓rp指針指向堆中NoHashObject對(duì)象的ptr成員???
    ?  Resource*?? rp?? =?? (Resource*)obj_ptr?? ;???
    ????
    ?  //初始化obj_ptr指向的NoHashObject對(duì)象的ptr成員???
    ?  rp?? =?? new?? Resource()?? ;???
    ?  //現(xiàn)在可以通過使用obj_ptr指針使用堆中的NoHashObject對(duì)象成員了???
    ?  ...?? ...???
    ????
    ?  delete?? rp?? ;//釋放資源???
    ?  temp?? =?? (char*)obj_ptr?? ;???
    ?  obj_ptr?? =?? NULL?? ;//防止懸掛指針產(chǎn)生???
    ?  delete?? []?? temp?? ;//釋放NoHashObject對(duì)象所占的堆空間.??
    ????
    ??? return 0;????
    ? }????
    ??? 上面的實(shí)現(xiàn)是麻煩的, 而且這種實(shí)現(xiàn)方式幾乎不會(huì)在實(shí)踐中使用, 但是我還是寫出來路, 因?yàn)槔斫馑? 對(duì)于我們理解C++內(nèi)存對(duì)象是有好處的. 對(duì)于上面的這么多強(qiáng)制類型轉(zhuǎn)換, 其最根本的是什么了? 我們可以這樣理解:????
    ????
    ??? 某塊內(nèi)存中的數(shù)據(jù)是不變的, 而類型就是我們戴上的眼鏡, 當(dāng)我們戴上一種眼鏡后, 我們就會(huì)用對(duì)應(yīng)的類型來解釋內(nèi)存中的數(shù)據(jù), 這樣不同的解釋就得到了不同的信息.????
    ????
    ??? 所謂強(qiáng)制類型轉(zhuǎn)換實(shí)際上就是換上另一副眼鏡后再來看同樣的那塊內(nèi)存數(shù)據(jù).????
    ????????
    ??? 另外要提醒的是, 不同的編譯器對(duì)對(duì)象的成員數(shù)據(jù)的布局安排可能是不一樣的, 比如, 大多數(shù)編譯器將NoHashObject的ptr指針成員安排在對(duì)象空間的頭4個(gè)字節(jié), 這樣才會(huì)保證下面這條語句的轉(zhuǎn)換動(dòng)作像我們預(yù)期的那樣執(zhí)行:????
    ????
    ? Resource*?? rp?? =?? (Resource*)obj_ptr?? ;?????
    ????
    ??? 但是, 并不一定所有的編譯器都是如此.????
    ????
    ??? 既然我們可以禁止產(chǎn)生某種類型的堆對(duì)象, 那么可以設(shè)計(jì)一個(gè)類, 使之不能產(chǎn)生棧對(duì)象嗎? 當(dāng)然可以.????
    ????
    ??? 五.禁止產(chǎn)生棧對(duì)象???
    ????
    ??? 前面已經(jīng)提到了, 創(chuàng)建棧對(duì)象時(shí)會(huì)移動(dòng)棧頂指針以“挪出”適當(dāng)大小的空間, 然后在這個(gè)空間上直接調(diào)用對(duì)應(yīng)的構(gòu)造函數(shù)以形成一個(gè)棧對(duì)象, 而當(dāng)函數(shù)返回時(shí), 會(huì)調(diào)用其析構(gòu)函數(shù)釋放這個(gè)對(duì)象, 然后再調(diào)整棧頂指針收回那塊棧內(nèi)存. 在這個(gè)過程中是不需要operator?? new/delete操作的, 所以將operator?? new/delete設(shè)置為private不能達(dá)到目的. 當(dāng)然從上面的敘述中, 你也許已經(jīng)想到了: 將構(gòu)造函數(shù)或析構(gòu)函數(shù)設(shè)為私有的, 這樣系統(tǒng)就不能調(diào)用構(gòu)造/析構(gòu)函數(shù)了, 當(dāng)然就不能在棧中生成對(duì)象了.????
    ????
    ??? 這樣的確可以, 而且我也打算采用這種方案. 但是在此之前, 有一點(diǎn)需要考慮清楚,那就是, 如果我們將構(gòu)造函數(shù)設(shè)置為私有, 那么我們也就不能用new來直接產(chǎn)生堆對(duì)象了, 因?yàn)閚ew在為對(duì)象分配空間后也會(huì)調(diào)用它的構(gòu)造函數(shù)啊. 所以, 我打算只將析構(gòu)函數(shù)設(shè)置為private. 再進(jìn)一步, 將析構(gòu)函數(shù)設(shè)為private除了會(huì)限制棧對(duì)象生成外, 還有其它影響嗎? 是的, 這還會(huì)限制繼承.????
    ????
    ??? 如果一個(gè)類不打算作為基類, 通常采用的方案就是將其析構(gòu)函數(shù)聲明為private.????
    ????
    ??? 為了限制棧對(duì)象, 卻不限制繼承, 我們可以將析構(gòu)函數(shù)聲明為protected, 這樣就兩全其美了. 如下代碼所示:????
    ????
    ? class?? NoStackObject???
    ? {???
    ?  protected:???
    ?   ~NoStackObject()?? {?? }???
    ?  public:???
    ?   void?? destroy()???
    ?   {???
    ?    delete?? this?? ;//調(diào)用保護(hù)析構(gòu)函數(shù)???
    ?   }???
    ? };?????
    ????
    ??? 接著, 可以像這樣使用NoStackObject類:????
    ????
    ? NoStackObject*?? hash_ptr?? =?? new?? NoStackObject()?? ;???
    ? ...?? ...?? //對(duì)hash_ptr指向的對(duì)象進(jìn)行操作???
    ? hash_ptr->destroy()?? ;?????
    ????
    ??? 呵呵, 是不是覺得有點(diǎn)怪怪的, 我們用new創(chuàng)建一個(gè)對(duì)象, 卻不是用delete去刪除它, 而是要用destroy方法. 很顯然, 用戶是不習(xí)慣這種怪異的使用方式的. 所以, 我決定將構(gòu)造函數(shù)也設(shè)為private或protected. 這又回到了上面曾試圖避免的問題, 即不用new, 那么該用什么方式來生成一個(gè)對(duì)象了? 我們可以用間接的辦法完成, 即讓這個(gè)類提供一個(gè)static成員函數(shù)專門用于產(chǎn)生該類型的堆對(duì)象. (設(shè)計(jì)模式中的singleton模式就可以用這種方式實(shí)現(xiàn). )讓我們來看看:????
    ????
    ? class?? NoStackObject???
    ? {???
    ?  protected:???
    ?   NoStackObject()?? {?? }???
    ?   ~NoStackObject()?? {?? }???
    ?  public:???
    ?   static?? NoStackObject*?? creatInstance()???
    ?   {???
    ?    return?? new?? NoStackObject()?? ;//調(diào)用保護(hù)的構(gòu)造函數(shù)???
    ?   }???
    ?   void?? destroy()???
    ?   {???
    ?    delete?? this?? ;//調(diào)用保護(hù)的析構(gòu)函數(shù)???
    ?   }???
    ? };?????
    ????
    ??? 現(xiàn)在可以這樣使用NoStackObject類了:????
    ????
    ? NoStackObject*?? hash_ptr?? =?? NoStackObject::creatInstance()?? ;???
    ? ...?? ...?? //對(duì)hash_ptr指向的對(duì)象進(jìn)行操作???
    ? hash_ptr->destroy()?? ;???
    ? hash_ptr?? =?? NULL?? ;?? //防止使用懸掛指針?????
    ????
    ??? 現(xiàn)在感覺是不是好多了, 生成對(duì)象和釋放對(duì)象的操作一致了. ??

    總結(jié)

    以上是生活随笔為你收集整理的只在堆上或只在栈上定义对象的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 毛片导航 | 韩国伦理片在线看 | 婷婷6月天| 91精彩刺激对白 | 午夜黄色网址 | 奇米狠狠777 | 久久视奸 | 亚洲色图 美腿丝袜 | 国产精品制服诱惑 | 蜜桃av中文字幕 | 亚洲永久免费精品 | 影音先锋欧美资源 | 国产精品久久中文字幕 | 自拍三区| 欧美综合亚洲图片综合区 | 日本福利一区二区 | 国产成人啪免费观看软件 | 黄色网在线 | 日本一区二区高清不卡 | 2020亚洲天堂 | 99热国产在线 | 婷婷丁香五 | 午夜免费福利小电影 | 久久久久久a | jizzjizz黄大片| 精品视频免费 | 亚洲黄色免费视频 | 欧美午夜精品久久久久久人妖 | 特黄色大片 | 无遮挡av| 中文字幕人妻熟女人妻a片 麻豆91视频 | 午夜欧美在线 | 99热精品在线播放 | 欧美第七页 | 91在线视频观看 | 澳门一级黄色片 | 亚洲一页 | 中国精品久久久 | 另类尿喷潮videofree | 亚洲高清一区二区三区 | 中文字幕亚洲乱码熟女一区二区 | 狠狠干2022 | 中国美女毛片 | 爱情岛论坛自拍亚洲品质极速最新章 | 我们的2018中文免费看 | 伊人网在线| 国产性猛交xxxⅹ交酡全过程 | www日本xxx | eeuss日韩| 日本特级黄色大片 | 久草免费在线视频观看 | 欧美黑人疯狂性受xxxxx野外 | 国产精品探花一区二区在线观看 | 自拍偷拍视频在线观看 | 麻豆精品久久久 | 欧美一级片a| 亚洲AV不卡无码一区二区三区 | 麻豆视频91 | 国产三级视频在线 | 青青草综合网 | 中文字幕久久av | 亚洲精品久久久久久久久久久 | 亲吻刺激视频 | 高潮毛片又色又爽免费 | 福利国产在线 | 秘密爱大尺度做爰呻吟 | 中文字幕欲求不满 | jizz中国少妇高潮出水 | 精品人妻一区二区免费 | 日本少妇激情 | 福利精品| 人人艹人人| 日本a级一区 | 午夜福利一区二区三区 | 成人免费在线电影 | 欧美日韩久久久久久 | 日本不卡一区二区在线观看 | 中文一区视频 | 和黑帮大佬的365 | 在线看黄色网址 | 成人精品在线播放 | 国产免费自拍 | 国产精品理论在线观看 | 好姑娘在线观看高清完整版电影 | 男女免费观看视频 | 国产女人高潮毛片 | 日本一区二区在线视频 | 久久久久久久久免费看无码 | 午夜激情影视 | 成年人免费网站视频 | 一区二区精品视频 | 天堂素人约啪 | 国产成人三级在线观看 | jizz中国少妇| 法国空姐电影在线观看 | 日韩久久精品一区二区 | 视频一区二区中文字幕 | 五月开心激情网 | 9191av|