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

SmartPtr
本博客已搬至:http://www.cnblogs.com/baiyanhuang/
posts - 29,comments - 176,trackbacks - 0
By SmartPtr(http://m.shnenglu.com/SmartPtr/)

auto_ptr是當(dāng)前C++標(biāo)準(zhǔn)庫(kù)中提供的一種智能指針,或許相對(duì)于boost庫(kù)提供的一系列眼花繚亂的智能指針, 或許相對(duì)于Loki中那個(gè)無(wú)所不包的智能指針,這個(gè)不怎么智能的智能指針難免會(huì)黯然失色。誠(chéng)然,auto_ptr有這樣那樣的不如人意,以至于程序員必須像使用”裸“指針那樣非常小心的使用它才能保證不出錯(cuò),以至于它甚至無(wú)法適用于同是標(biāo)準(zhǔn)庫(kù)中的那么多的容器和一些算法,但即使如此,我們?nèi)匀徊荒芊裾J(rèn)這個(gè)小小的auto_ptr所蘊(yùn)含的價(jià)值與理念。
  auto_ptr的出現(xiàn),主要是為了解決“被異常拋出時(shí)發(fā)生資源泄漏”的問(wèn)題。即如果我們讓資源在局部對(duì)象構(gòu)造時(shí)分配,在局部對(duì)象析構(gòu)時(shí)釋放。這樣即使在函數(shù)執(zhí)行過(guò)程時(shí)發(fā)生異常退出,也會(huì)因?yàn)楫惓D鼙WC局部對(duì)象被析構(gòu)從而保證資源被釋放。auto_ptr就是基于這個(gè)理念而設(shè)計(jì), 這最早出現(xiàn)在C++之父Bjarne Stroustrup的兩本巨著TC++PL和D&E中,其主題為"resource acquisition is initialization"(raii,資源獲取即初始化),然后又在Scott Meyer的<<More Effective C++>>中相關(guān)章節(jié)的推動(dòng)下,被加入了C++標(biāo)準(zhǔn)庫(kù)。
  下面我就列出auto_ptr的源代碼,并詳細(xì)講解每一部分。因?yàn)闃?biāo)準(zhǔn)庫(kù)中的代碼要考慮不同編譯器支持標(biāo)準(zhǔn)的不同而插入了不少預(yù)編譯判斷,而且命名可讀性不是很強(qiáng)(即使是侯捷老師推薦的SGI版本的stl,可讀性也不盡如人意), 這里我用了Nicolai M. Josuttis(<<The C++ standard library>>作者)寫的一個(gè)auto_ptr的版本,并做了少許格式上的修改以易于分析閱讀。

 

namespace std
{
 template
<class T>
 
class auto_ptr 
 {
 
private:
  T
* ap; 
 
public:

  
// constructor & destructor ----------------------------------- (1)
  explicit auto_ptr (T* ptr = 0throw() : ap(ptr){}

  
~auto_ptr() throw() 
  {
   delete ap;
  }

  
  
// Copy & assignment --------------------------------------------(2)
  auto_ptr (auto_ptr& rhs) throw() :ap(rhs.release()) {}
  template
<class Y>  
  auto_ptr (auto_ptr
<Y>& rhs) throw() : ap(rhs.release()) { }

  auto_ptr
& operator= (auto_ptr& rhs) throw() 
  {
   reset(rhs.release());
   
return *this;
  }
  template
<class Y>
  auto_ptr
& operator= (auto_ptr<Y>& rhs) throw() 
  {
   reset(rhs.release());
   
return *this;
  }

  
// Dereference----------------------------------------------------(3)
  T& operator*() const throw() 
  {
   
return *ap;
  }
  T
* operator->() const throw() 
  {
   
return ap;
  }

  
// Helper functions------------------------------------------------(4)
  
// value access
  T* get() const throw() 
  {
   
return ap;
  }

  
// release ownership
  T* release() throw()
  {
   T
* tmp(ap);
   ap 
= 0;
   
return tmp;
  }

  
// reset value
  void reset (T* ptr=0throw() 
  {
   
if (ap != ptr) 
   {
    delete ap;
    ap 
= ptr;
   }
  }

  
// Special conversions-----------------------------------------------(5)
  template<class Y>
  
struct auto_ptr_ref
  {
   Y
* yp;
   auto_ptr_ref (Y
* rhs) : yp(rhs) {}
  };

  auto_ptr(auto_ptr_ref
<T> rhs) throw() : ap(rhs.yp) { }
  auto_ptr
& operator= (auto_ptr_ref<T> rhs) throw() 
  {  
   reset(rhs.yp);
   
return *this;
  }
  template
<class Y>
  
operator auto_ptr_ref<Y>() throw() 
  {
   
return auto_ptr_ref<Y>(release());
  }
  template
<class Y>
  
operator auto_ptr<Y>() throw()
  {
   
return auto_ptr<Y>(release());
  }
 };
}


1 構(gòu)造函數(shù)與析構(gòu)函數(shù)
auto_ptr在構(gòu)造時(shí)獲取對(duì)某個(gè)對(duì)象的所有權(quán)(ownership),在析構(gòu)時(shí)釋放該對(duì)象。我們可以這樣使用auto_ptr來(lái)提高代碼安全性:
int* p = new int(0);
auto_ptr<int> ap(p);
從此我們不必關(guān)心應(yīng)該何時(shí)釋放p, 也不用擔(dān)心發(fā)生異常會(huì)有內(nèi)存泄漏。
這里我們有幾點(diǎn)要注意:
1) 因?yàn)閍uto_ptr析構(gòu)的時(shí)候肯定會(huì)刪除他所擁有的那個(gè)對(duì)象,所有我們就要注意了,一個(gè)蘿卜一個(gè)坑,兩個(gè)auto_ptr不能同時(shí)擁有同一個(gè)對(duì)象。像這樣:
int* p = new int(0);
auto_ptr<int> ap1(p);
auto_ptr<int> ap2(p);
因?yàn)閍p1與ap2都認(rèn)為指針p是歸它管的,在析構(gòu)時(shí)都試圖刪除p, 兩次刪除同一個(gè)對(duì)象的行為在C++標(biāo)準(zhǔn)中是未定義的。所以我們必須防止這樣使用auto_ptr.
2) 考慮下面這種用法:
int* pa = new int[10];
auto_ptr<int> ap(pa);
因?yàn)閍uto_ptr的析構(gòu)函數(shù)中刪除指針用的是delete,而不是delete [],所以我們不應(yīng)該用auto_ptr來(lái)管理一個(gè)數(shù)組指針。
3) 構(gòu)造函數(shù)的explicit關(guān)鍵詞有效阻止從一個(gè)“裸”指針隱式轉(zhuǎn)換成auto_ptr類型。
4) 因?yàn)镃++保證刪除一個(gè)空指針是安全的, 所以我們沒有必要把析構(gòu)函數(shù)寫成:
~auto_ptr() throw()
{
 if(ap) delete ap;
}

2 拷貝構(gòu)造與賦值
與引用計(jì)數(shù)型智能指針不同的,auto_ptr要求其對(duì)“裸”指針的完全占有性。也就是說(shuō)一個(gè)”裸“指針不能同時(shí)被兩個(gè)以上的auto_ptr所擁有。那么,在拷貝構(gòu)造或賦值操作時(shí),我們必須作特殊的處理來(lái)保證這個(gè)特性。auto_ptr的做法是“所有權(quán)轉(zhuǎn)移”,即拷貝或賦值的源對(duì)象將失去對(duì)“裸”指針的所有權(quán),所以,與一般拷貝構(gòu)造函數(shù),賦值函數(shù)不同, auto_ptr的拷貝構(gòu)造函數(shù),賦值函數(shù)的參數(shù)為引用而不是常引用(const reference).當(dāng)然,一個(gè)auto_ptr也不能同時(shí)擁有兩個(gè)以上的“裸”指針,所以,拷貝或賦值的目標(biāo)對(duì)象將先釋放其原來(lái)所擁有的對(duì)象。
這里的注意點(diǎn)是:
1) 因?yàn)橐粋€(gè)auto_ptr被拷貝或被賦值后, 其已經(jīng)失去對(duì)原對(duì)象的所有權(quán),這個(gè)時(shí)候,對(duì)這個(gè)auto_ptr的提領(lǐng)(dereference)操作是不安全的。如下:
int* p = new int(0);
auto_ptr<int> ap1(p);
auto_ptr<int> ap2 = ap1;
cout<<*ap1; //錯(cuò)誤,此時(shí)ap1只剩一個(gè)null指針在手了
這種情況較為隱蔽的情形出現(xiàn)在將auto_ptr作為函數(shù)參數(shù)按值傳遞,因?yàn)樵诤瘮?shù)調(diào)用過(guò)程中在函數(shù)的作用域中會(huì)產(chǎn)生一個(gè)局部對(duì)象來(lái)接收傳入的auto_ptr(拷貝構(gòu)造),這樣,傳入的實(shí)參auto_ptr就失去了其對(duì)原對(duì)象的所有權(quán),而該對(duì)象會(huì)在函數(shù)退出時(shí)被局部auto_ptr刪除。如下:
void f(auto_ptr<int> ap){cout<<*ap;}
auto_ptr<int> ap1(new int(0));
f(ap1);
cout<<*ap1; //錯(cuò)誤,經(jīng)過(guò)f(ap1)函數(shù)調(diào)用,ap1已經(jīng)不再擁有任何對(duì)象了。
因?yàn)檫@種情況太隱蔽,太容易出錯(cuò)了, 所以auto_ptr作為函數(shù)參數(shù)按值傳遞是一定要避免的。或許大家會(huì)想到用auto_ptr的指針或引用作為函數(shù)參數(shù)或許可以,但是仔細(xì)想想,我們并不知道在函數(shù)中對(duì)傳入的auto_ptr做了什么, 如果當(dāng)中某些操作使其失去了對(duì)對(duì)象的所有權(quán), 那么這還是可能會(huì)導(dǎo)致致命的執(zhí)行期錯(cuò)誤。 也許,用const reference的形式來(lái)傳遞auto_ptr會(huì)是一個(gè)不錯(cuò)的選擇。

2)我們可以看到拷貝構(gòu)造函數(shù)與賦值函數(shù)都提供了一個(gè)成員模板在不覆蓋“正統(tǒng)”版本的情況下實(shí)現(xiàn)auto_ptr的隱式轉(zhuǎn)換。如我們有以下兩個(gè)類
class base{};
class derived: public base{};
那么下列代碼就可以通過(guò),實(shí)現(xiàn)從auto_ptr<derived>到auto_ptr<base>的隱式轉(zhuǎn)換,因?yàn)閐erived*可以轉(zhuǎn)換成base*類型
auto_ptr<base> apbase = auto_ptr<derived>(new derived);

3) 因?yàn)閍uto_ptr不具有值語(yǔ)義(value semantic), 所以auto_ptr不能被用在stl標(biāo)準(zhǔn)容器中。
所謂值語(yǔ)義,是指符合以下條件的類型(假設(shè)有類A):
A a1;
A a2(a1);
A a3;
a3 = a1;
那么
a2 == a1, a3 == a1
很明顯,auto_ptr不符合上述條件,而我們知道stl標(biāo)準(zhǔn)容器要用到大量的拷貝賦值操作,并且假設(shè)其操作的類型必須符合以上條件。


3 提領(lǐng)操作(dereference)
提領(lǐng)操作有兩個(gè)操作, 一個(gè)是返回其所擁有的對(duì)象的引用, 另一個(gè)是則實(shí)現(xiàn)了通過(guò)auto_ptr調(diào)用其所擁有的對(duì)象的成員。如:
struct A
{
 void f();
}
auto_ptr<A> apa(new A);
(*apa).f();
apa->f();
當(dāng)然, 我們首先要確保這個(gè)智能指針確實(shí)擁有某個(gè)對(duì)象,否則,這個(gè)操作的行為即對(duì)空指針的提領(lǐng)是未定義的。

4 輔助函數(shù)
1) get用來(lái)顯式的返回auto_ptr所擁有的對(duì)象指針。我們可以發(fā)現(xiàn),標(biāo)準(zhǔn)庫(kù)提供的auto_ptr既不提供從“裸”指針到auto_ptr的隱式轉(zhuǎn)換(構(gòu)造函數(shù)為explicit),也不提供從auto_ptr到“裸”指針的隱式轉(zhuǎn)換,從使用上來(lái)講可能不那么的靈活, 考慮到其所帶來(lái)的安全性還是值得的。
2) release,用來(lái)轉(zhuǎn)移所有權(quán)
3) reset,用來(lái)接收所有權(quán),如果接收所有權(quán)的auto_ptr如果已經(jīng)擁有某對(duì)象, 必須先釋放該對(duì)象。

5 特殊轉(zhuǎn)換
這里提供一個(gè)輔助類auto_ptr_ref來(lái)做特殊的轉(zhuǎn)換,按照標(biāo)準(zhǔn)的解釋, 這個(gè)類及下面4個(gè)函數(shù)的作用是:使我們得以拷貝和賦值non-const auto_ptrs, 卻不能拷貝和賦值const auto_ptrs. 我無(wú)法非常準(zhǔn)確的理解這兩句話的意義,但根據(jù)我們觀察與試驗(yàn),應(yīng)該可以這樣去理解:沒有這些代碼,我們本來(lái)就可以拷貝和賦值non-const的auto_ptr和禁止拷貝和賦值const的auto_ptr的功能, 只是無(wú)法拷貝和賦值臨時(shí)的auto_ptr(右值), 而這些輔助代碼提供某些轉(zhuǎn)換,使我們可以拷貝和賦值臨時(shí)的auto_ptr,但并沒有使const的auto_ptr也能被拷貝和賦值。如下:
auto_ptr<int> ap1 = auto_ptr<int>(new int(0));
auto_ptr<int>(new int(0))是一個(gè)臨時(shí)對(duì)象,一個(gè)右值,一般的拷貝構(gòu)造函數(shù)當(dāng)然能拷貝右值,因?yàn)槠鋮?shù)類別必須為一個(gè)const reference, 但是我們知道,auto_ptr的拷貝函數(shù)其參數(shù)類型為reference,所以,為了使這行代碼能通過(guò),我們引入auto_ptr_ref來(lái)實(shí)現(xiàn)從右值向左值的轉(zhuǎn)換。其過(guò)程為:
1) ap1要通過(guò)拷貝 auto_ptr<int>(new int(0))來(lái)構(gòu)造自己
2) auto_ptr<int>(new int(0))作為右值與現(xiàn)有的兩個(gè)拷貝構(gòu)造函數(shù)參數(shù)類型都無(wú)法匹配,也無(wú)法轉(zhuǎn)換成該種參數(shù)類型
3) 發(fā)現(xiàn)輔助的拷貝構(gòu)造函數(shù)auto_ptr(auto_ptr_ref<T> rhs) throw()
4) 試圖將auto_ptr<int>(new int(0))轉(zhuǎn)換成auto_ptr_ref<T>
5) 發(fā)現(xiàn)類型轉(zhuǎn)換函數(shù)operator auto_ptr_ref<Y>() throw(), 轉(zhuǎn)換成功,從而拷貝成功。
從而通過(guò)一個(gè)間接類成功的實(shí)現(xiàn)了拷貝構(gòu)造右值(臨時(shí)對(duì)象)
同時(shí),這個(gè)輔助方法不會(huì)使const auto_ptr被拷貝, 原因是在第5步, 此類型轉(zhuǎn)換函數(shù)為non-const的,我們知道,const對(duì)象是無(wú)法調(diào)用non-const成員的, 所以轉(zhuǎn)換失敗。當(dāng)然, 這里有一個(gè)問(wèn)題要注意, 假設(shè)你把這些輔助轉(zhuǎn)換的代碼注釋掉,該行代碼還是可能成功編譯,這是為什么呢?debug一下, 我們可以發(fā)現(xiàn)只調(diào)用了一次構(gòu)造函數(shù),而拷貝構(gòu)造函數(shù)并沒有被調(diào)用,原因在于編譯器將代碼優(yōu)化掉了。這種類型優(yōu)化叫做returned value optimization,它可以有效防止一些無(wú)意義的臨時(shí)對(duì)象的構(gòu)造。當(dāng)然,前提是你的編譯器要支持returned value optimization。

  可見,auto_ptr短短百來(lái)行的代碼,還是包含了不少"玄機(jī)"的。 

posted on 2007-07-05 17:48 SmartPtr 閱讀(12105) 評(píng)論(3)  編輯 收藏 引用

FeedBack:
# re: auto_ptr解析 [未登錄]
2007-07-14 22:08 | walkspeed
多看代碼,多分析代碼,學(xué)習(xí)代碼中的實(shí)現(xiàn)。不錯(cuò)。  回復(fù)  更多評(píng)論
  
# re: auto_ptr解析 [未登錄]
2008-01-22 22:36 | ron
呵呵,正愁不知道auto_ptr的原理呢, 現(xiàn)在想想,該方法實(shí)現(xiàn)的挺巧妙的,
有一點(diǎn),就是在special conversion 下的
operator auto_ptr<Y>() throw()
是什么時(shí)候會(huì)用的到的呢?  回復(fù)  更多評(píng)論
  
# re: auto_ptr解析
2013-10-10 14:33 | lzxbill7
@ron
同疑惑這里,至少?zèng)]在auto_ptr內(nèi)部使用。唯一想到的是將auto_ptr<T>轉(zhuǎn)變?yōu)閍uto_ptr<Y>時(shí),這就得讓使用者顯示轉(zhuǎn)化了。  回復(fù)  更多評(píng)論
  

只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   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>
            亚洲日本视频| 国产精品女主播在线观看| 久久久久久久久久久久久久一区| 欧美日韩中文字幕综合视频| 欧美freesex交免费视频| 老司机久久99久久精品播放免费| 99精品黄色片免费大全| 亚洲日本乱码在线观看| 一本色道精品久久一区二区三区| 亚洲精品一区二| 欧美**字幕| 欧美电影专区| 亚洲国产欧美久久| 日韩一区二区精品在线观看| 亚洲作爱视频| 欧美在线观看一区二区三区| 巨胸喷奶水www久久久免费动漫| 久久精品国产亚洲aⅴ| 麻豆精品视频在线| 欧美午夜无遮挡| 黄色小说综合网站| 99精品热6080yy久久| 羞羞漫画18久久大片| 久热精品视频在线免费观看| 亚洲欧洲久久| 久久久久久久综合| 国产精品久久91| 亚洲国产91精品在线观看| 99精品视频免费全部在线| 欧美在线视频全部完| 亚洲激情在线观看| 久久久91精品国产一区二区精品| 欧美福利网址| 黄色成人av网站| 午夜视频在线观看一区二区| 亚洲成人在线免费| 最近看过的日韩成人| 欧美在线免费观看亚洲| 欧美日韩精品免费在线观看视频| 国产欧美丝祙| 中文av一区特黄| 欧美激情精品久久久久| 欧美一区二区视频网站| 国产精品日韩在线一区| 亚洲免费观看高清在线观看 | 另类图片综合电影| 国产日韩精品电影| 亚洲综合精品| 亚洲欧洲日韩在线| 久久综合伊人77777蜜臀| 国产亚洲欧美一区二区| 午夜精品久久久久久99热软件| 免费成人高清在线视频| 久久精品国亚洲| 国产有码在线一区二区视频| 亚洲欧美日韩综合国产aⅴ| 亚洲毛片在线免费观看| 欧美日本精品在线| 99国内精品| 亚洲最快最全在线视频| 欧美性大战久久久久| 亚洲一区二区高清视频| 99人久久精品视频最新地址| 欧美人与性动交cc0o| 免费观看国产成人| 久久婷婷麻豆| 在线日韩av永久免费观看| 久久一日本道色综合久久| 亚洲欧美日韩精品久久久久| 国产精品视频1区| 欧美一区二区在线免费播放| 午夜精品福利一区二区三区av| 欧美黄色视屏| 一区二区三区精品在线 | 中文高清一区| 国产精品视频精品| 久久人91精品久久久久久不卡| 午夜精品久久久久久久久久久| 欧美视频一区二区三区四区| 亚洲欧美日韩在线高清直播| 欧美亚洲三区| 亚洲国产二区| 日韩亚洲欧美成人| 国产欧美日韩综合一区在线播放| 欧美一区二区视频在线| 久久久久国产精品一区| 亚洲美女少妇无套啪啪呻吟| 一区二区三区视频观看| 国产一区视频观看| 亚洲欧洲久久| 国产一区导航| 亚洲精品1区2区| 国产精品网站在线观看| 欧美成人一区二免费视频软件| 欧美成人中文字幕在线| 亚洲免费在线播放| 女人色偷偷aa久久天堂| 午夜精品影院| 欧美/亚洲一区| 欧美影院午夜播放| 免费看精品久久片| 欧美一区二区三区视频免费播放| 久久国产综合精品| 亚洲作爱视频| 久久一综合视频| 亚洲综合成人婷婷小说| 美国十次了思思久久精品导航| 亚洲图片欧洲图片日韩av| 久久尤物视频| 久久久久国产精品人| 欧美日韩中文另类| 欧美成人a∨高清免费观看| 国产精品视频一| 9久re热视频在线精品| 亚洲国产精品久久久久| 欧美一区影院| 亚洲欧美999| 欧美日韩一区二区三区在线视频| 久久精品国产一区二区电影 | 久久久久一区二区三区四区| 国产精品xvideos88| 亚洲国产精品日韩| 一区二区三区在线免费播放| 亚洲欧美国产精品桃花| 国产日产精品一区二区三区四区的观看方式 | 国产午夜精品一区理论片飘花| 午夜精品三级视频福利| 欧美日韩国产高清视频| 欧美激情中文字幕一区二区| 黑人一区二区三区四区五区| 亚洲图片在线观看| 夜夜嗨av一区二区三区免费区| 欧美诱惑福利视频| 欧美一区二区三区在线观看| 欧美性生交xxxxx久久久| 亚洲精品社区| 亚洲美女精品一区| 欧美精品在线免费播放| 亚洲高清不卡| 亚洲美女淫视频| 免费影视亚洲| 亚洲国产欧美不卡在线观看| 日韩视频在线观看免费| 欧美精选午夜久久久乱码6080| 免费成人av在线| 亚洲第一二三四五区| 久久亚洲精品一区| 欧美成年人视频网站欧美| 亚洲第一页在线| 欧美福利电影在线观看| 亚洲欧洲一区二区三区| 夜夜夜久久久| 国产精品久久国产精麻豆99网站| 亚洲美女视频在线观看| 一区二区三区蜜桃网| 国产精品进线69影院| 欧美在线观看一区二区| 亚洲第一精品久久忘忧草社区| 激情成人亚洲| 欧美福利在线| 亚洲图片欧洲图片日韩av| 久久国产精品亚洲va麻豆| 尤物九九久久国产精品的分类| 久久精品国产亚洲精品| 欧美国产日韩一区二区在线观看| 亚洲欧洲在线视频| 国产精品久久久久9999高清| 久久国产精品亚洲77777| 亚洲国产高清在线观看视频| 亚洲女性裸体视频| 亚洲第一黄网| 欧美亚男人的天堂| 久久综合五月| 亚洲免费在线观看| 欧美激情女人20p| 久久9热精品视频| 亚洲乱码久久| 国产一区二区精品丝袜| 欧美久久久久久| 久久av二区| 这里只有精品视频| 亚洲高清自拍| 久久久精品久久久久| 一本色道久久88综合亚洲精品ⅰ| 国产精品久久久久一区二区三区共| 欧美午夜精彩| 欧美在线91| 91久久精品国产91性色| 欧美在线亚洲一区| 亚洲最新在线视频| 在线激情影院一区| 国产精品美女久久久久久2018| 亚洲永久免费| 亚洲免费av网站| 欧美激情国产日韩| 久久久亚洲欧洲日产国码αv| 日韩视频第一页| 在线观看亚洲专区| 国产亚洲一区在线| 国产精品色婷婷|