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

清風竹林

ぷ雪飄絳梅映殘紅
   ぷ花舞霜飛映蒼松
     ----- Do more,suffer less

C++通用刪除器設計

C++通用刪除器設計

版本:0.1

最后修改:2010-11-15

撰寫:李現民


概述

很久以前,我寫過一篇短文討論如何在C++項目中避免使用delete的設想,基本方法是使用域(scope)對象或std::auto_ptr代替。盡管當時已經討論在所有可能的情況,但后面在實際項目實施中發現效果并不好。原因是方面的,比如在使用std::auto_ptr時會存在以下不得因素:

  1. 可能的額外開銷外(其實很?。?;

  2. 你需要時刻小心對象所有權的問題。盡管可能只需要稍微注意一下就可以了,但似乎沒有任何程序員喜歡過提心吊膽的日子;

  3. 你不能在容器(比如std::vector)中存儲std::auto_ptr對象;


基于以上原因,類似于Text* pText = new Text;這種直接在堆上申請內存的方式還是在代碼得到了大量應用。而接下來就是如何安全、有效的回收這些內存的問題,這也正是本文所討論的話題。

回收單個堆對象

// delete a object pointer and reset it
template<class T> void delete_null(T*& p)
{
// check if T is incomplete type, if it is, the compiler will report an error
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
(void) sizeof(type_must_be_complete);
// delete the pointer and reset it
delete p;
p =NULL;
}


這是一個模板函數,它主要有三個作用:

第一個作用是檢查被刪除對象的類型完整性。這通常無法引起人們的重視,但在某些情況下可能會導致未定義行為,比如以下代碼:

Text* pText = new Text;
void* pData = pText;
delete pData;

Text*類對象pText 被轉換成了擁有void*對象pData,并對pData 調用了delete 刪除操作。在這種情況下編譯器的行為是未知的,但至少有一點:由于編譯器無法推導pData 的原始類型,因此無法調用對象的析構函數。

// check if T is incomplete type, if it is, the compiler will report an error
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
(void) sizeof(type_must_be_complete);

這兩句代碼可以檢查被刪除對象的類型完整性。其效果發生在編譯期,如果對類型不完整的對象調用delete_null 刪除操作,將引起編譯錯誤。它沒有運行期開銷,因此使用delete_null 帶來的安全性實際上免費的。

更加詳細的解釋可以參考boost庫中的checked_delete.hpp。

delete_null 的第二個作用是回收堆對象,這沒有什么可說的。

delete_null 的第三個作用是將對象指針設置為NULL,這主要是為了應對指針有效性檢查,屬于常規手段。

另外,注意到delete_null 被設計為一個模板函數,在發布版本(Release)中,它將以內聯代碼(inline)的形式存在,因此不會有運用期函數調用開銷。


回收容器中的堆對象


// delete container (std::vector, std::list) items and reset them to NULL
template< typename InputIterator > void delete_null(InputIterator first, InputIterator last)
{
while(last != first)
{
delete_null(*first);
++first;
}
}

// delete functor, used for iterative delete
struct deleter
{
template< typename T > void operator()(T*& p)
{
delete_null(p);
}
};


這段代碼分為兩部分:一個同樣叫delete_null 的模板函數與一個名為deleter的仿函數。

先來看第一部分,它同樣叫delete_null,與前面介紹的那個版本所不同的是它接受一對迭代器作用輸入條件,其作用是回收[first, last) 范圍內所有堆對象。與std::for_each等很多STL標準算法類似,該函數可以同時應用于普通數組或存儲單值的標準容器(包括std::vector, std::list, std::set等,不包含std::map)。


第二部分比較有意思:它是一個仿函數。它可以在一定程度上代替delete_null(first, last),以下代碼展示了分別使用這兩種方式回收容器中的堆對象的方法

typedef std::vector<Text*> TextPack;
TextPack uTexts1, uTexts2;
const int datasize = 100;
for (int i= 0; i< datasize; ++i)
{
uTexts1.push_back(new Text);
uTexts2.push_back(new Text);
}

//
使用delete_null
delete_null(uTexts1.begin(), uTexts1.end());
// 使用deleter
std::for_each(uTexts2.begin(), uTexts2.end(), deleter());


可以看到前者稍微簡潔一些(包括最終的匯編代碼),那么問題來了:為什么還需要代碼量更大一些的deleter 仿函數?

理由是:并不是所有存儲堆對象的集合都是直接存儲對象指針的。比如可以將指針存儲在std::map中“值”部分,甚至有些自定義集合只提供了遍歷函數(類似于std::for_each),但并不公開迭代器接口。在這些情況下,我們就可以使用deleter 仿函數進行堆對象回收。



posted on 2010-11-15 14:46 李現民 閱讀(3285) 評論(16)  編輯 收藏 引用 所屬分類: design

評論

# re: C++通用刪除器設計 2010-11-15 22:11 ,。。

自作聰明,無語。。。  回復  更多評論   

# re: C++通用刪除器設計[未登錄] 2010-11-15 23:09 Jeff

博主,有問題請教:
1、為什么不直接使用boost中提供的smart ptr呢?
2、你的實現是否是“異常安全”呢?  回復  更多評論   

# re: C++通用刪除器設計 2010-11-16 09:18 李現民

@Jeff
唉, 這批評還真犀利呀!
1. 不直接使用boost中的智能指針最直接的原因是boost不穩定,而且并不是boost中的所有特性都對項目有幫助的。你可能會問為什么我不自己實現一個,一個類似于shared_ptr的東西,除了那一點性能損失外,真正的原因是我還沒有發現讓我不得不用的理由。而且,項目中有很多地方是不能直接調用析構函數的,而是需要單獨寫一個Destroy的函數,因為時機。
2. 關于異常安全,我想,如果析構函數本身是異常安全的話,那么我的代碼本身應該算異常安全了吧?反之,如果析構函數本身不安全的話,那無論采用什么方法析構都是有問題的。

如果我的想法有什么問題的話,請不吝指正,非常感謝。
  回復  更多評論   

# re: C++通用刪除器設計 2010-11-16 10:52 空明流轉

@李現民

扯淡,有什么不穩定的。

shared_ptr是一個完全OK的選擇。至于性能損失,我還真沒遇到過。一個atomic的add,能有多少性能損耗?能和你的res alloc和free比么?

還有,RAII本身就是一種Idiom。你覺得不適用,只是因為你對RAII這個Idiom本身不熟悉而已。  回復  更多評論   

# re: C++通用刪除器設計 2010-11-16 11:16 李現民

@空明流轉
我所指的“不穩定”是指boost一直在開發,里面有長期積累下來的庫,也有新加入的庫,只是加入到項目中,新庫在未證明其穩定性之前也有可能被使用,而這可能導致一些問題。

另外, 你說得對,相比于資源的分配與回收,shared_ptr的開銷是可以忽略的,但我們的系統中現在還沒有這樣的機制,而且我說過了,真正的原因是我尚未發現讓我不得不用它的理由。

最后, 我其實是很贊同使用RAII的,實際上,我們已經在陸續使用它了。

感謝回復!  回復  更多評論   

# re: C++通用刪除器設計 2010-11-16 13:40 陳梓瀚(vczh)

@李現民
那你就自己寫一個shared_ptr吧,最多發現不穩定的時候你還可以改嘛,改著改著就穩定了。  回復  更多評論   

# re: C++通用刪除器設計 2010-11-16 13:41 陳梓瀚(vczh)

@李現民
不得不用的理由有很多的,譬如說我最推崇的一條就是:“不使用它會浪費人類的時間”  回復  更多評論   

# re: C++通用刪除器設計[未登錄] 2010-11-16 22:37 Jeff

@李現民
恐怕你誤解我的意思了。我并沒有批評的意思,只是想搞清楚一些問題。
關于boost的“不穩定”,在實際項目的運用時,只選擇使用某一個版本的boost使用是就好了。對一個項目而言,boost的版本是穩定的。這樣能避免一些配置管理的問題。
另外,使用boost的一個原因就是避免重復造輪子:)當然,一定要選擇boost中質量高、穩定性好的功能才能在項目中使用?!叭∑渚A、去其糟粕”,呵呵……
  回復  更多評論   

# re: C++通用刪除器設計 2010-11-17 10:36 李現民

@陳梓瀚(vczh)
看了這么多回復, 如果我沒想錯的話,是不是大家都推崇使用shared_ptr替代原始對象指針?如果多數人都這認為的話,那肯定是有道理的。如你所言,看來有時間我得去仔細研究一下shared_ptr了。

我現在能想到的問題是,假如我自己寫了一個shared_ptr加入到了舊的項目中,那么所有其它使用該對象的地方(包括參數)是否都必須帶著shared_ptr<T>的聲明呢?

感謝回復,不忙的時候研究一下。  回復  更多評論   

# re: C++通用刪除器設計 2010-11-17 10:40 李現民

@Jeff
沒有, 非常歡迎你的評論。大家的回復讓我想了很多,這些都是非常意外而重要的收獲。

其實, 最直接的問題是:我沒有權利在項目中引入一個像boost 這樣大的庫,因此這不但限制了應用,也限制了我的眼界。  回復  更多評論   

# re: C++通用刪除器設計 2010-11-17 17:34 冬瓜

這個和boost::shared_ptr沒關系吧~~~~,
我看了一下,它的做用是對刪除void *的指針,會產生一個編譯器的錯誤。以避免一些人員將T *指針轉換成void *,再刪除,而造成沒有執行析構函數的問題。不過,這種情況非常少。

shared_ptr的作用是0引用時刪除。  回復  更多評論   

# re: C++通用刪除器設計 2010-11-17 17:58 李現民

@冬瓜
是這樣的, 大家覺得如果直接用shared_ptr的話就沒有必要寫一個delete_null函數了
  回復  更多評論   

# re: C++通用刪除器設計 2010-11-17 18:24 星綻紫輝

沒有絕對的,指針引用計數用在比較復雜的環境(大塊的資源使用、隊列資源)中非常有用(比如內存池的分配和釋放),你可以寫自己的AddRef和DelRef函數來管理資源, 但是通常簡單類就沒必要了,如果連簡單的實現類、模式類、UI類都這么搞,你會暈的。。。  回復  更多評論   

# re: C++通用刪除器設計 2010-11-17 19:42 李現民

@星綻紫輝
呵呵, 受教了  回復  更多評論   

# re: C++通用刪除器設計 2010-11-18 10:09 冬瓜

@李現民
你的delete_null和shared_ptr是兩個完全不同的東西。
作用目標都不一樣~  回復  更多評論   

# re: C++通用刪除器設計 2010-11-18 10:32 陳梓瀚(vczh)

@李現民
shared_ptr只是一個例子哈,當然也可以用來刪除東西,因為它支持的轉換比起C++的指針轉換還是更嚴格的。

我自己也實現了一次,在ptr<A>和ptr<B>進行轉換用的是dynamic_cast,這樣如果一個類型沒有虛函數就會報錯,因此我不會因為錯誤轉換了指針而導致析構的時候發生問題,就非常安全了。  回復  更多評論   

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            亚洲欧洲日本一区二区三区| 狠狠色综合色综合网络| 制服丝袜激情欧洲亚洲| 亚洲高清自拍| 亚洲国产福利在线| 亚洲国产精品综合| 91久久夜色精品国产九色| 亚洲美女av在线播放| 亚洲天堂偷拍| 欧美一级久久| 猛男gaygay欧美视频| 欧美区一区二| 国产欧美一区二区三区沐欲| 狠狠色丁香久久婷婷综合丁香 | 国产专区一区| 亚洲激情一区二区三区| 中日韩高清电影网| 久久亚裔精品欧美| 日韩亚洲欧美一区| 午夜精品久久久久久99热| 久久久午夜电影| 欧美日韩国产精品专区| 国产日韩欧美综合精品| 亚洲精品美女在线| 欧美在线免费观看视频| 亚洲国产va精品久久久不卡综合| 99re6热只有精品免费观看| 欧美在线视频在线播放完整版免费观看 | 在线播放亚洲一区| 亚洲黄色天堂| 久久激情婷婷| 亚洲精品美女在线| 久久久91精品国产一区二区精品| 久久亚洲私人国产精品va| 欧美午夜宅男影院在线观看| 在线成人中文字幕| 久久精品一区中文字幕| 日韩一二在线观看| 欧美精品国产精品日韩精品| 亚洲精品午夜精品| 久久精品av麻豆的观看方式| 欧美午夜精品| aa级大片欧美| 久久久之久亚州精品露出| 日韩视频在线一区二区| 久久亚洲美女| 国内精品免费午夜毛片| 校园激情久久| 亚洲一区二区高清| 欧美日韩综合| 国产精品99久久不卡二区| 亚洲国产精品一区在线观看不卡 | 欧美成人午夜77777| 亚洲欧洲av一区二区三区久久| 欧美日韩mp4| 亚洲精品一区二区网址| 免费观看成人鲁鲁鲁鲁鲁视频| 欧美一区二区精品在线| 国产精品资源| 欧美一级视频| 亚洲专区在线视频| 国产片一区二区| 久久久久久9999| 久久看片网站| 亚洲国产精品成人| 亚洲区第一页| 欧美四级电影网站| 午夜精品成人在线视频| 亚洲综合色激情五月| 国产欧美精品在线| 久久亚洲影音av资源网| 久久综合亚洲社区| 日韩亚洲精品视频| 在线视频日本亚洲性| 国产欧美精品| 麻豆精品一区二区综合av| 久久综合国产精品| 日韩视频免费观看高清完整版| 亚洲乱码一区二区| 国产欧美va欧美不卡在线| 久久人人爽人人| 欧美—级高清免费播放| 亚洲天堂久久| 久久动漫亚洲| 亚洲精品国产精品国自产观看浪潮| 亚洲国产合集| 国产精品乱码人人做人人爱| 欧美在线视频网站| 久久综合久久88| 在线一区二区视频| 欧美一区二区大片| 日韩视频第一页| 欧美一级日韩一级| 亚洲国语精品自产拍在线观看| 夜夜嗨av一区二区三区免费区| 国产亚洲精品一区二区| 91久久精品美女高潮| 国产网站欧美日韩免费精品在线观看| 亚洲第一在线视频| 亚洲制服少妇| 亚洲淫性视频| 亚洲色图综合久久| 亚洲第一区在线观看| 一卡二卡3卡四卡高清精品视频| 国产精品一区二区欧美| 亚洲国产日韩在线一区模特| 国产日韩专区| 一本久久a久久精品亚洲| 伊人久久大香线蕉av超碰演员| 亚洲精选视频免费看| 又紧又大又爽精品一区二区| 国产精品99久久不卡二区| 亚洲国内自拍| 欧美在线播放| 亚洲欧美日韩另类精品一区二区三区| 久久一区欧美| 久久久精品999| 国产精品国色综合久久| 亚洲激情一区二区| 亚洲国产高清高潮精品美女| 亚洲欧美激情精品一区二区| 一区二区三区精品久久久| 乱人伦精品视频在线观看| 久久久亚洲欧洲日产国码αv| 国产精品免费区二区三区观看| 亚洲欧洲三级| 亚洲免费高清| 欧美大片免费观看在线观看网站推荐 | 亚洲一区在线播放| 久久婷婷麻豆| 老司机精品导航| 尹人成人综合网| 久久久国产一区二区| 久久久久久久性| 国产综合av| 久久九九国产| 欧美va日韩va| 亚洲精品久久久久久久久久久久 | 久久中文字幕一区二区三区| 国产色视频一区| 香港成人在线视频| 久久久久九九视频| 韩国成人福利片在线播放| 久久疯狂做爰流白浆xx| 久久人人97超碰人人澡爱香蕉| 国产最新精品精品你懂的| 久久精品视频导航| 欧美顶级艳妇交换群宴| 亚洲经典一区| 欧美日韩欧美一区二区| 一区二区日本视频| 欧美伊人久久| 狠狠色丁香婷婷综合| 麻豆国产精品va在线观看不卡| 欧美国产亚洲另类动漫| 99v久久综合狠狠综合久久| 欧美激情国产日韩| 在线视频你懂得一区| 久久久久久久久久看片| 亚洲人成在线观看一区二区 | 欧美一区二区三区在线| 国产午夜精品美女毛片视频| 久久精品国产99| 欧美黄在线观看| 亚洲午夜精品久久久久久浪潮| 国产精品国产亚洲精品看不卡15| 亚洲小视频在线观看| 久久久久在线| 99精品热视频只有精品10| 国产农村妇女精品一区二区| 久久亚洲春色中文字幕| 日韩一级片网址| 久久网站热最新地址| 夜夜嗨av一区二区三区四区| 国产日韩欧美在线| 欧美精品一区在线播放| 欧美呦呦网站| 日韩午夜黄色| 麻豆91精品91久久久的内涵| 日韩视频一区二区在线观看| 国产精品网站一区| 欧美另类久久久品 | 国产精品欧美日韩一区| 久久综合九色综合欧美狠狠| 一区二区三区四区五区在线| 蜜桃av一区二区在线观看| 亚洲一区二区三区三| 亚洲欧洲一区二区在线观看| 国产日韩欧美综合一区| 欧美性猛交xxxx乱大交蜜桃| 蜜桃久久精品一区二区| 午夜久久久久久| 9国产精品视频| 亚洲国产精品福利| 欧美1区2区3区| 久久久久久伊人| 久久大综合网| 欧美一区二区三区在线观看| 中日韩高清电影网| 亚洲毛片在线看|