Guru of the Week 條款11:物件等同(Object Identity)問題 (轉)
GotW #11 ntity
著者:Herb Sutter
翻譯:kingofark
[宣告]:本文內容取自網站上的Guru of the Week欄目,其著作權歸原著者本人所有。譯者kingofark在未經原著者本人同意的情況下翻譯本文。本翻譯內容僅供自學和參考用,請所有閱讀過本文的人不要擅自轉載、傳播本翻譯內容;本翻譯內容的人請在閱讀瀏覽後,立即刪除其。譯者kingofark對違反上述兩條原則的人不負任何責任。特此宣告。
Revision 1.0
Guru of the Week 條款11:等同(Object Identity)問題:namespace prefix = o ns = "urn:schemas--com::office" />
難度:5 / 10
(“我到底是誰?”這個問題蘊含著如何確定兩個指標是否真的指向同一個物件的問題)
[問題]
測試語句“this != &other” 是一個防止自賦值(self-assingment)的常見編碼手法。那麼,要到達這個“防止自賦值(self-assingment)”目的,現有的語句是否是必要的和/或充分的呢?為什麼?或者為什麼不?如果答案是否定的,你又如何進行修改呢?注意要區分“protecting against Murphy vs. protecting against Machiavelli”。(* 譯註:見本條款末尾)
T& T::operator=( const T& other ){
if( this != &other ) { // the test in question
// ...
}
return *this;
}
[解答]
一個簡短的解答:從技術上來看,它既不是必要的也不是充分的。在實踐當中,它工作得頗好但也有可能在C++標準中被修改。
* 論點:異常-(Murphy)
如果operator=()是異常-安全的(exception-safe),那麼你並不需要檢查自賦值(self-assignment)。這裡有兩個上的不利因素:a)如果可以進行自賦值(self-assignment)檢查的話,那就可以進行徹底的從而省略掉賦值操作;b)如果程式碼被寫成異常-安全的(exception-safe),那麼同時也使得程式碼損失了一部分效率(這也即是說“paranoia has a price principle”,意即“偏執狂也有權衡代價的原則”)。
* 不是論點的論點:多重繼承
過去曾有人把多重繼承與本條款討論的問題聯絡起來,但實際上這個問題與多重繼承沒有任何關係。我們的討論的是一個涉及到C++標準怎樣讓你比較兩個指標的技術性問題。
* 論點:運算子的過載(Machiavelli)
雖然一些類可能會提供它們自己的operator&(),但是問題中對自賦值(self-assignment)的檢查卻很可能不如你所期望的那樣運作,而是做一些完全不同的事情。用“protecting against Machiavelli”來意寓這種情況是因為,我們只能推測編寫operator=()的人也許大概知道他實現的類是不是也過載了operator&()。
要注意,一個類可能也會提供一個T::operator!=(),但這與本問題無關——它並不影響我們對自賦值(self-assignment)的檢查,原因是:由於一個被過載的運算子至少有一個引數的型別必須是“類(class)”型別,因而我們不可能編寫一個包含有兩個T*型引數的T::operator!=()。
後記1
下面是一個所謂的“程式碼(code joke)”。信不信由你,竟然真有一些並無惡意但無疑是被誤導了的程式碼編寫者曾企圖使用這樣的程式碼:
T::T( const T& other ) {
if( this != &other ) {
// ...
}
}
怎麼樣?你能第一眼就看出毛病嗎?
後記2
值得注意的是,還有另外一些情況,在這些情況當中,指標的比較也不是多數人光憑直覺就能考慮周到的。比如:
1. James Kanze指出,把指標比較成字串的行為是未定義的。其原因(我還未見有人給出過)是C++標準明確規定:允許將字串存放在重疊的區域以作為一種空間最佳化方案。
2. 一般來說,雖然像諸如和>=等內建(built-in)運算子的運算結果在各種特定情況下(比如,同一個陣列中的兩個指向物件的指標)都有著良好的定義,但你還是不能用這些運算子對任意的指標進行比較。標準庫的使用也是基於這種限制的,其中規定:less<>以及其它庫必須給出各指標的次序(ordering),以使得我們可以建立,比方說,一個key為指標型別的map,即map
(* 譯註:關於Murphy和Machiavelli,侯捷先生在其系列書評的《C++/大系》中提到:“就我的英文程度而言,[Sutter99](即《Exceptional C++》)讀起來不若[Meyers96] (即《More Effective C++》)和[Meyers98] (即《Effective C++2/e》)那般平順,原因是其中用了很多釐語、口語、典故。舉個例子,Morphy law是什麼,大家知道嗎?(莫菲定律說:會出錯的,一定會出錯。)Machiavelli又代表了什麼意思?(義大利政治家,以詐術聞名。)”
在這裡,本條款的譯者kingofark只能慚愧的說kingofark自己也沒有完全理解本條款使用Murphy和Machiavelli兩個詞的用意。
Machiavelli:馬基雅維利,尼克爾1469-1527義大利政治理論家,他的著作 君主論(1513年)闡述了一個意志堅定的統治者不顧道德觀念的如何獲得並保持其權力;馬基雅弗利,義大利新興資產階級思想政治家,歷史學家。)
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-990914/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Guru of the Week 條款13:物件導向程式設計 (轉)物件程式設計
- Guru of the Week 條款19:自動轉換 (轉)
- Guru of the Week 條款27:轉呼叫函式 (轉)函式
- Guru of the Week 條款28:“Fast Pimpl”技術 (轉)AST
- Guru of the Week 條款09:記憶體管理(上篇) (轉)記憶體
- Guru of the Week 條款10:記憶體管理(下篇) (轉)記憶體
- Guru of the Week 條款24:編譯級防火牆 (轉)編譯防火牆
- Guru of the Week 條款30附錄:介面原則 (轉)
- Guru of the Week 條款05:覆寫虛擬函式 (轉)函式
- Guru of the Week 條款07:編譯期的依賴性 (轉)編譯
- Guru of the Week 條款14:類之間的關係(上篇) (轉)
- Guru of the Week 條款15:類之間的關係(下篇) (轉)
- Guru of the Week 條款23:物件的生存期(第二部分) (轉)物件
- Guru of the Week 條款22:物件的生存期(第一部分) (轉)物件
- Guru of the Week 條款16:具有最大可複用性的通用Containers (轉)AI
- Guru of the Week 條款08:GotW挑戰篇——異常處理的安全性 (轉)Go
- Guru of the Week 條款21:程式碼的複雜性(第二部分) (轉)
- C++ articles:Guru of the Week #1 (轉)C++
- Guru of the week:#18 迭代指標. (轉)指標
- Guru of the Week 條款20:程式碼的複雜性(第一部分) (轉)
- Guru of the week:#17 型別對映. (轉)型別
- Guru of the week:#19 自動型別轉換. (轉)型別
- C++ articles:Guru of the Week #4 -- Class Mechantics (轉)C++
- Guru of The week #20 程式碼的複雜性 Ⅰ. (轉)
- C++ articles:Guru of the Week #3:使用標準庫 (轉)C++
- Guru of the Week #5:虛擬函式的重新定義 (轉)函式
- 第8條:理解“物件等同性”這一概念物件
- More Effective C++ 條款11 (轉)C++
- 物件等同性判斷物件
- Week 11 Problems
- SQLServer IDENTITY_INSERT問題SQLServerIDE
- 條款13 以物件管理資源物件
- 我理解的Persistent Object Identity in HibernateObjectIDE
- 關於內嵌物件(Embedded Object)快取設計的問題物件Object快取
- Oracle關於week的計算問題Oracle
- Java面試之基礎題---物件ObjectJava面試物件Object
- C++ 11 - STL - 函式物件(Function Object) (下)C++函式物件FunctionObject
- week2 kuangbin 題單 最短路問題 + 並查集問題並查集