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

asm, c, c++ are my all
-- Core In Computer
posts - 139,  comments - 123,  trackbacks - 0

[轉(zhuǎn)]智能指針與微妙的隱式轉(zhuǎn)換

??? C++
雖然是強(qiáng)類型語言,但是卻還不如 Java C# 那么足夠的強(qiáng)類型,原因是允許的隱式轉(zhuǎn)換太多

  • C 語言繼承下來的基本類型之間的隱式轉(zhuǎn)換
  • T* 指針到 void* 的隱式轉(zhuǎn)換
  • non-explicit constructor 接受一個(gè)參數(shù)的隱式轉(zhuǎn)換
  • 從子類到基類的隱式轉(zhuǎn)換 ( 安全)
  • const non-const 的同類型的隱式轉(zhuǎn)換 ( 安全 )

除開上面的五種隱式轉(zhuǎn)換外, C++ 的編譯器還非常聰明,當(dāng)沒法直接隱式轉(zhuǎn)換的時(shí)候,它會(huì)嘗試間接的方式隱式轉(zhuǎn)換,這使得有時(shí)候的隱式轉(zhuǎn)換非常的微妙,一個(gè)誤用會(huì)被編譯器接受而會(huì)出現(xiàn)意想不到的結(jié)果。例如假設(shè)類 A 有一個(gè) non-explicit constructor ,唯一的參數(shù)是類 B ,而類 B 也有一個(gè) non-explicit constructor 接受類型 C ,那么當(dāng)試圖用類型 C 的實(shí)例初始化類 A 的時(shí)候,編譯器發(fā)現(xiàn)沒有直接從類型 C 構(gòu)造的過程,但是呢,由于類 B 可以被接受,而類型 C 又可以向類型 B 隱式轉(zhuǎn)換,因此從 C->B->A 的路就通暢了。這樣的隱式轉(zhuǎn)換多數(shù)時(shí)候沒什么大礙,但是不是我們想要的,因?yàn)樗赡茉斐梢恍┪⒚畹?/span> bug 而難以捕捉。

?

為了在培訓(xùn)的時(shí)候展示棧上析構(gòu)函數(shù)的特點(diǎn)和自動(dòng)資源管理,準(zhǔn)備下面的一個(gè)例子,結(jié)果測(cè)試的時(shí)候由于誤用而發(fā)現(xiàn)一些問題。 ( 測(cè)試的 IDE Visual Studio 2005)

class A

{

public:

A(){ a = 100; }

int a;

void f();

};

?

A * pa = new A();

std::auto_ptr<A>? p = pa;? // 無意這樣使用的,本意是 std::auto_ptr<A> p(pa)

p->f();

?

這個(gè)寫法是拷貝構(gòu)造函數(shù)的形式,顯然從 T* 是不能直接拷貝構(gòu)造的 auto_ptr 的,但是編譯器會(huì)嘗試其他的路徑來轉(zhuǎn)換成 auto_ptr 來拷貝構(gòu)造,因此如果存在一個(gè)中間的 ,這個(gè)類能接受從 T* 的構(gòu)造,而 同時(shí)auto_ptr也能接受從類X 的構(gòu)造,那編譯器就會(huì)很高興的生成這樣的代碼。

這段代碼在 VC6 上是通不過的,因?yàn)?/span> VC6 auto_ptr 實(shí)現(xiàn)就只有一個(gè)接受 T* 指針的 explicit constructor .

但是 C++ Standard 的修正規(guī)范中,要求 auto_ptr 還應(yīng)該有個(gè)接受 auto_ptr_ref constructor 。那么這個(gè) auto_ptr_ref 是什么呢?按照 C++ Standard 的解釋 :

Template auto_ptr_ref holds a reference to an auto_ptr. It is used by the auto_ptr conversions to allow auto_ptr objects to be passed to and returned from functions.

有興趣可以參考 Scott Meyers " auto_ptr update page "? ( http://www.awprofessional.com/content/images/020163371X/autoptrupdate%5Cauto_ptr_update.html ?)講訴auto_ptr的歷史.

?

再回到前面的代碼,本來應(yīng)該是通不過的編譯,但是 VC2005 的編譯器卻沒有任何怨言的通過 ( 即使把警告等級(jí)設(shè)置到 4) 。結(jié)果運(yùn)行的時(shí)候卻崩潰了,出錯(cuò)在 auto_ptr 的析構(gòu)函數(shù) ,delete 的指針?biāo)赶虻刂肥?/span> 100 ,而如果在 p->f() 后面加上一句 cout << pa->a << endl; 發(fā)現(xiàn)輸出結(jié)果為 0 。 為什么會(huì)這樣,原因就是前面所訴的間接的隱式轉(zhuǎn)換,這與 VC 2006 auto_ptr auto_ptr_ref 實(shí)現(xiàn)有關(guān),看看 P.J.Plauger 是怎么實(shí)現(xiàn)的 :

// auto_ptr_ref

template<class _Ty>

struct auto_ptr_ref

{

// proxy reference for auto_ptr copying

auto_ptr_ref(void *_Right)

: _Ref(_Right)

{?? // construct from generic pointer to auto_ptr ptr

}

void *_Ref;// generic pointer to auto_ptr ptr

};

?

// construct auto_ptr from an auto_ptr_ref object

auto_ptr(auto_ptr_ref<_Ty> _Right) _THROW0()

{

// construct by assuming pointer from _Right auto_ptr_ref

_Ty **_Pptr = (_Ty **)_Right._Ref;

_Ty *_Ptr = *_Pptr;

*_Pptr = 0;

// release old

_Myptr = _Ptr;

// reset this

}

?

這樣代碼通過編譯的原因也就清楚了, A* -> void * -> auto_ptr_ref -> auto_ptr -> copy constructor -> accept. 好長(zhǎng)的隱式轉(zhuǎn)換鏈 , -_-, C++ 編譯器太聰明了。

那么為什么最后會(huì)出現(xiàn)指針被破壞的結(jié)果呢,原因在 auto_ptr 的實(shí)現(xiàn),因?yàn)榘凑?/span> C++ Standard 要求, auto_ptr_ref 應(yīng)該是包含一個(gè) auto_ptr 的引用,因此 auto_ptr 的構(gòu)造函數(shù)也就假設(shè)了 auto_ptr_ref 的成員 _Ref 是一個(gè)指向 auto_ptr 的指針。 auto_ptr 中只有一個(gè)成員就是 A* 的指針,因此指向 auto_ptr 對(duì)象的指針相當(dāng)于就是個(gè) A** 指針,因此上面 auto_ptr auto_ptr_ref 構(gòu)造的代碼是合理的。 但是由于罪惡的 void* 造成了一條非常寬敞的隱式轉(zhuǎn)換的道路, A* 指針也能夠被接受,因此把 A* 當(dāng)作 A** 來使用,結(jié)果可想而知, A* 指向地址的前 4 個(gè)字節(jié) ( 因?yàn)?/span> 32 OS) 被拷貝出來,而這四個(gè)字節(jié)被賦值為 0( *_Pptr=0 ) 。 所以出現(xiàn)了最后的結(jié)果是 _Myptr 值為 100 ,而 pa->a 0

如果要正確執(zhí)行結(jié)果,只要保證是個(gè) A** 指針就行了,有兩個(gè)方法

第一, auto_ptr_ref 所包含的引用是指向的 auto_ptr 對(duì)象

A * p = new A();

std::auto_ptr<A> pt( new A() );

std::auto_ptr_ref<A> ra( pt );

std::auto_ptr<A> pb = ra ;

pb->f();

?

第二,直接用二級(jí)指針

A * p = new A();

std::auto_ptr<A> pb = &p;? // 這句話后 , p 將等于 0

pb->f();

?

當(dāng)然第二種是利用了 VC2005 的實(shí)現(xiàn)而造出來的,看著很別扭 ,:) 。 我不明白 P.J.Plauger 為什么用 void * ,而不是用 auto_ptr<T>& ,因?yàn)槿魏沃羔樁寄茈[式轉(zhuǎn)換為 void * ,這樣的危險(xiǎn)性大多了。并且如果用了 auto_ptr<T>& ,從 auto_ptr_ref 構(gòu)造也容易寫得更簡(jiǎn)單清楚,看看以前的實(shí)現(xiàn)方式吧,仍然是 P.J.Plauger 的,但是版本低了點(diǎn):

template<class _Ty>

struct auto_ptr_ref

{

// proxy reference for auto_ptr copying

?

auto_ptr_ref(auto_ptr<_Ty>& _Right)

: _Ref(_Right)

{

// construct from compatible auto_ptr

}

auto_ptr<_Ty>& _Ref;

// reference to constructor argument

};

auto_ptr(auto_ptr_ref<_Ty> _Right) _THROW0()

: _Myptr(_Right._Ref.release())

{

// construct by assuming pointer from _Right auto_ptr_ref

}

?

這樣的實(shí)現(xiàn)方法,顯然不能接受任何指針的隱式轉(zhuǎn)換,也就防止一開始的那種錯(cuò)誤寫法,并且也是符合 C++ Standard 的要求的。

SGI STL auto_ptr_ref 的實(shí)現(xiàn)則是包含了一個(gè) T* 的指針,構(gòu)造 auto_ptr 時(shí)候直接從 auto_ptr_ref 中拷貝這個(gè)指針,因此這樣的實(shí)現(xiàn)可以上代碼編譯通過,運(yùn)行也正確,不過不符合 C++ Standard 。

?

總結(jié)一下,危險(xiǎn)的潛伏bug的隱式轉(zhuǎn)換應(yīng)該被杜絕的,特別是 void * 的隱式轉(zhuǎn)換和構(gòu)造函數(shù)的隱式轉(zhuǎn)換,因此建議是 :

  • 慎用 void * ,因?yàn)?/span> void * 必須要求你知道轉(zhuǎn)換前的實(shí)現(xiàn),因此更適合用在底層的、性能相關(guān)的內(nèi)部實(shí)現(xiàn)。
  • 單一參數(shù)的構(gòu)造函數(shù)應(yīng)該注意是否允許隱式轉(zhuǎn)換,如果不需要,加上 explicit 。例如 STL 容器中 vector 接受從 int 的構(gòu)造函數(shù),用于預(yù)先申請(qǐng)空間,這樣的構(gòu)造函數(shù)顯然不需要隱式轉(zhuǎn)換,因此加上了 explicit 。
  • 重載函數(shù)中,如果可能,就用更有明確意義的名字替代重載,因?yàn)殡[式轉(zhuǎn)換也許會(huì)帶來一些意想不到的麻煩。
  • 避免隱式轉(zhuǎn)換不等于是多用顯示轉(zhuǎn)換。 Meyers Effective C++ 中提到,即使 C++ 風(fēng)格的顯示轉(zhuǎn)換也應(yīng)該盡量少用,最好是改進(jìn)設(shè)計(jì)。
posted on 2006-07-25 00:37 Jerry Cat 閱讀(781) 評(píng)論(0)  編輯 收藏 引用

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



<2006年5月>
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

常用鏈接

留言簿(7)

隨筆檔案

最新隨筆

搜索

  •  

最新評(píng)論

閱讀排行榜

評(píng)論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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在线播放一区| 欧美精品久久一区| 国产精品入口麻豆原神| 尤物99国产成人精品视频| 亚洲电影免费在线 | 先锋影音国产精品| 久久久久久亚洲综合影院红桃 | 欧美成人精品在线观看| 欧美高清成人| 亚洲天堂男人| 免费不卡中文字幕视频| 欧美天堂在线观看| 加勒比av一区二区| 一区二区三区欧美在线| 久久婷婷久久| 亚洲天堂成人在线观看| 狼人天天伊人久久| 国产精品久久久久久一区二区三区| 国产日韩三区| 在线视频欧美精品| 欧美电影专区| 久久精品视频亚洲| 国产精品一页| 亚洲一区二区不卡免费| 欧美黄免费看| 久久久天天操| 国产自产在线视频一区| 亚洲综合日本| 日韩一二三区视频| 欧美福利电影网| 樱花yy私人影院亚洲| 性欧美精品高清| 亚洲天堂av高清| 欧美久久一区| 亚洲人成在线观看网站高清| 久久久久www| 午夜欧美视频| 国产女主播在线一区二区| 亚洲无线视频| 99天天综合性| 欧美色区777第一页| 99精品视频免费观看| 亚洲国产精品va在线看黑人| 久久综合九九| 亚洲国产精品成人综合色在线婷婷| 小黄鸭精品aⅴ导航网站入口| 99在线精品视频在线观看| 欧美日韩高清在线一区| 99精品福利视频| 99综合精品| 国产精品日韩久久久久| 性做久久久久久| 亚洲免费在线观看| 国产欧美视频一区二区三区| 欧美一区二区成人6969| 欧美亚洲日本网站| 国内视频一区| 欧美激情区在线播放| 欧美人在线观看| 亚洲女人天堂成人av在线| 亚洲视频在线一区| 国产亚洲激情| 欧美黑人多人双交| 欧美日韩中文| 久久国内精品自在自线400部| 美女性感视频久久久| 久久天堂精品| 老司机一区二区| 日韩天堂av| 在线视频精品一| 国产亚洲精品久| 亚洲国产精品久久91精品| 欧美日韩精品伦理作品在线免费观看| 在线综合欧美| 久久国产精品72免费观看| 亚洲国产日韩在线| 中国成人在线视频| 伊人久久婷婷色综合98网| 亚洲日本va在线观看| 国产精品久久久久久久午夜| 久久综合电影| 国产精品国产| 欧美高清一区| 国产精品少妇自拍| 亚洲电影一级黄| 国产欧美91| 亚洲欧洲日本国产| 国产一区二区三区在线观看精品 | 亚洲高清毛片| 99精品国产在热久久下载| 国产日韩精品在线播放| 欧美韩日亚洲| 国产伪娘ts一区| 亚洲精品女人| 国产日韩欧美三区| 亚洲免费观看在线观看| 精品成人乱色一区二区| 正在播放欧美视频| 日韩亚洲欧美在线观看| 久久精品一区蜜桃臀影院| 亚洲欧美激情视频| 欧美另类久久久品| 欧美国产在线视频| 韩国精品久久久999| 中文在线一区| 中文av一区特黄| 欧美激情久久久久| 欧美成人综合在线| 狠狠综合久久av一区二区老牛| 亚洲午夜av| 亚洲婷婷综合色高清在线| 欧美激情视频一区二区三区免费 | 欧美激情在线观看| 国产主播喷水一区二区| 亚洲一品av免费观看| 一区二区三区 在线观看视| 蜜桃伊人久久| 欧美高清视频一区二区三区在线观看| 国内精品视频在线播放| 欧美有码在线视频| 欧美资源在线观看| 国产欧美日韩精品a在线观看| 久久精品99久久香蕉国产色戒| 亚洲永久字幕| 欧美日韩国产一区精品一区 | 西西裸体人体做爰大胆久久久| 亚洲免费视频成人| 国产精品久久久久国产精品日日| 99re热这里只有精品免费视频| 日韩午夜中文字幕| 欧美三级电影一区| 亚洲视频你懂的| 欧美在线看片| 精品动漫3d一区二区三区免费| 久久艳片www.17c.com| 欧美丰满高潮xxxx喷水动漫| 亚洲激情专区| 欧美日韩综合视频网址| 亚洲亚洲精品三区日韩精品在线视频| 亚洲女人小视频在线观看| 国产欧美日韩综合一区在线播放| 亚洲欧美日韩精品久久久| 久久久久久婷| 亚洲精品日韩一| 国产精品久久久久久亚洲毛片| 亚洲欧美日韩在线播放| 久久综合五月| 日韩小视频在线观看专区| 国产精品久久久久久久9999| 午夜亚洲性色福利视频| 欧美xart系列高清| 亚洲视频福利| 国产一区二区三区免费不卡| 另类天堂av| 亚洲免费久久| 久久五月婷婷丁香社区| 亚洲精品专区| 国产日韩欧美精品| 欧美肥婆在线| 欧美一区二区三区在线看| 欧美高清在线视频| 先锋影音网一区二区| 亚洲国产影院| 国产亚洲二区| 欧美日韩亚洲一区二区三区在线观看 | 亚洲专区免费| 欧美成人精品影院| 性欧美精品高清| 亚洲精品视频在线播放| 国产精品午夜久久| 欧美顶级艳妇交换群宴| 亚洲欧美一区二区激情| 亚洲国产精品毛片| 久久精品国产免费观看| 99在线视频精品| 一区二区在线免费观看| 国产精品毛片| 欧美精品一区二区在线播放| 久久精品国产视频| 亚洲尤物视频在线| 亚洲日本免费| 欧美激情亚洲激情| 久久久久久久久一区二区| 亚洲一区二区在| 99v久久综合狠狠综合久久| 狠狠入ady亚洲精品| 国产精品丝袜91| 国产精品国产三级国产| 国产视频在线观看一区二区三区| 久久久久久亚洲精品杨幂换脸 | 国产日产欧美一区| 欧美午夜宅男影院|