Herb Sutter的對話#30:It's an Object-ful Lifetime (轉)
-ful Lifetime(WQ譯):namespace prefix = o ns = "urn:schemas--com::office" />
那是在假日的前幾天。難得一次, 沒有截止期限的壓迫—我所從事的專案都已經按時完成了。
我經常在原始碼庫中閒逛以作為消遣。當研究其他員的程式碼時,我時常學到新的技巧—以及應該避免的技巧。 我偶然發現了一個有趣的東西,它被濃縮在下面的小程式中:
class T
{
public:
T & ref(){ return *this;}
};
void f(T &);
int main()
{
f(T().ref());
}
起先 ,我沒了解ref()的意圖,因此我移除了對它的—我預料它應該能夠工作:
int main()
{
f(T());
}
然而,當我編譯它時,提示有一個錯誤一在臨時上繫結了一個非const的引用。 我拍了一下腦袋—這當然是不允許的!我回想起Guru的講解,就在我第一次碰到這個問題的時候。
" 此禁令的一個理由是要避免一些微妙的,"她曾經說過。"我的孩子 , 考慮下列情況:"
class U
{
//...whatever...
};
void takesAndModifiesU( U & u)
{
// performs actions that modify the state of u
}
class V
{
public:
operator U();
};
void g()
{
V v;
//...
takesAndModifiesU;( v)
//...
}
"如果繫結被允許,編譯器會呼叫型別轉換操作,構造一個臨時的U物件。然後這個無名的臨時物件將被傳給takesAndModifiesU並被修改,然後在函式呼叫完成後被丟棄。最初的物件v,根本就沒有被動過-這將給寫這個函式的人以極大的困擾。"
但是,我還是被困擾了。我不明白最初的f(T().ref());語句怎麼可以編譯的—它還是在一個臨時物件上繫結了一個非const的引用啊。
"你不能侷限在不變性上,我的孩子,"Guru震驚了我—來自於真實世界的,而不是記憶中的。"轉而想一下lvalue和rvalue。神聖的標準告訴我們T()形式的一個顯式型別轉換產生一個rvalue。 rvalue只能繫結到一個const的引用,而lvalue沒有這個限制。另一方面,返回引用的函式,其結果是得到一個lvalue[1]. 因此編譯器能將非const的引用繫結在ref()的結果上。"
"於是,只要我呼叫一個返回引用的函式就沒問題了,"我答道。 " 嗨—賦值運算子返回引用,因此我可以寫 f(T() = T());。多妙!"我來勁了。 "我能想出這個技巧有很多用途"。
"小心,我的孩子。 如此不尋常的技巧是危險的,不應該輕易使用。 的確,我認為至少有一問題,關於物件生命期的,會導致未定義行為。"
" 那個是..." 我催促道。
" 先自己想,午飯之後吧,"Guru緩緩答道。在遠處,我看見一些同事已經準備去吃部門的假日聚餐了。我抓起外套,加入了他們,前往附近的一家飯店。
不知何故,我們實際上設法避免在吃飯時討論購物。 討論集中在我們喜愛的假日電影上,comparing the various remakes of Miracle on 34th Street, and whether Alistair Sim or Patrick Stewart made a better Scrooge。 (My vote was for Stewart。) Bob surprised me, though — I figured his favorite character would be the Grinch, but instead he waxed poetic on It's A Wonderful Life.(WQ注:Sorry,由於和技術無關,而又實在譯不好,所以沒譯。)
當我們吃完飯回來,我感覺很好。我在桌前坐下並開始沉思Guru所指的是什麼。 最後,當我努力保持眼睛睜開時,我明白了:
class U
{
T & t_;
public:
U( T & t) : t_( t ) {}
};
{//... some block pe ...
U u( (T() = T()) );
//...
}
一旦u物件完成構造,臨時物件的生命期就結束了,而u物件會帶著一個懸掛引用被留了下來。
就好象T物件從來沒有存在過,我陷入沉思中。
"好的,George,"我聽到了Guru的聲音,"你已經得到了你的願望。你從來就沒有出生過。"
"嗯? George是誰?"我轉向Guru。
"當然是你,"Guru答道。我一看到她,就認識到我正在做夢—那種你明知道是夢,但走到哪裡都跟著你的夢。"你是George Bailey。 你構造的物件從來沒有存在過。我的工作就是向你說明當涉及未定義行為時會發生什麼。"
在遠處,我看到一個條幅:"歡迎來到Bobville。"
"Bobville?" 我問,畏懼於這個名字。
"城鎮是由你的死對頭Bob控制,"Guru說道。 "他也是銀行的擁有者 , 和開發部的頭兒。讓我們沿主要街道散步一下。"
當我們向前走的時候,我看見了不能言狀的驚駭—沒有分隔的整塊程式碼,被命名為i和j的變數,和"NULL指標的反引用於此"的商業廣告牌。在一個街道拐角上,我看見了一些程式設計師正毫無愧色地複製-貼上程式碼。
我看見Kerry駕駛正駕駛著一輛出租汽車。我示意他停下來。
"把我帶離這裡,Kerry," 我在鑽入車廂時喊道。 "把我帶回辦公室,那個我們寫出理性程式碼的地方"。
"Kerry?我的名字是Ernie(搖獎機)。 我不懂寫程式碼; 我只是開計程車的。"我們從Wendy旁駛過,她穿著警服。Kerry揮手向她示意。知道它是一個夢,而我沒有被設定為注意他的行動,我忽略了他。
我們在一棟廢棄的辦公大樓前停下。 我跳出車跑進去。我找到了一塊白板,它上面有一些不爽的程式碼,於是重寫了它:
{//... some block scope ...
T tmp;
U u( tmp );
}
就在我放下書寫筆時,我被驚醒了。
"哇 !" 我自言自語著,一邊去餐廳拿我能找到的最濃的咖啡。
注:
[1] ISO/IEC 14882:1998(E), "International Standard, Programming Languages — C++", clauses 5.2.3, 8.5.3, and 3.10 respectively.
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-996672/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Tuples Herb Sutter(陶章志譯) (轉)
- Herb Sutter談Dennis Ritchie
- C++大師Herb Sutter加盟微軟,面對Codeproject侃侃而談。 (轉)C++微軟Project
- 網友對sars病毒事件的對話(轉)事件
- 關於openssl應用的對話 (轉)
- 對話#25:Getting to the Point (轉)
- 對話方塊中對成批控制元件的操作 (轉)控制元件
- Borland與Microsoft關於Delphi的對話 (轉)ROS
- FREQUENTIS3020S內話系統維護筆記S3筆記
- Kerberos ticket lifetime及其它ROS
- 對話方塊背景色的設定 (轉)
- Rust 生命週期 - lifetime in fnRust
- Rust 生命週期 - lifetime in structRustStruct
- 對話即資料流:智慧對話的新方法
- VC實現對話方塊上資訊的顯示 (轉)
- 訪談 | 對話版主【ScUpax0s】— 學習要保持開放的態度
- 關於專案經理的職業發展的對話(轉)
- 關於資料的笑話 30 則
- 關於資料的笑話30則
- 進一步學習對話方塊(轉)
- 對話#28:Contracts, Promises, and Mere Semantics (轉)Promise
- 資料探勘者與資料探勘青年的對話(轉)
- 白話k8s-Pod的組成K8S
- 智慧聊天對話機器人的對比機器人
- 孫宇晨對話韓媒:NFT是“Web3.0 轉型”的關鍵Web
- 有關屬性對話方塊(property sheet )的幾個提示 (轉)
- InstallShield自定義對話方塊模板程式碼(轉)
- 重新顯示 Windows 98 歡迎對話方塊(轉)Windows
- InstallShield自定義對話方塊淺談(三) (轉)
- InstallShield自定義對話方塊淺談(四) (轉)
- InstallShield自定義對話方塊淺談(五) (轉)
- 對話系統的前世今生
- 電話機器人是如何實現對話的?機器人
- 對話系統任務綜述與基於POMDP的對話系統
- 利用非對話語料來豐富對話生成模型模型
- 對話方塊的選單、控制元件使用COMMAND_UI (轉)控制元件UI
- 對話方塊只出一次的2種解決方法 (轉)
- 用匯編輕鬆地寫基於對話方塊的程式 (轉)