C++ Object Model 答客問 (1)
C++ Object Model 答客問 (1)
侯捷 jjhou@ccca.nctu.edu.tw
2000.03.25 第一次發表於
清大.楓橋驛站(140.114.87.5).電腦書訊版(Computer/CompBook)
本文將於日後整理於 侯捷網站
侯捷網站:www.jjhou.com
----------------------------------------------------------------
FeiYu wrote (1999/12/29) :
> Dear Sir:
> 看了Inside C++ Object Model後,有幾點想和你討論:
>
> 1. 文中多次出現「內化」、「擴張」等詞(尤其在constrctor)
> 中譯本內中英對照表並未加以標註,建議你把他加進去,
> 因為這些字眼實在很少在其他書中看到。
>
> 2. p.26中的程式:
> void rotate (X datum,const X* pointer,const X& reference)
> {
> (*pointer).rotate ();
> reference.rotate ();
> datum.rotate ();
> } // end function
> 在VC中編譯會出現轉型上的錯誤,必須拿掉參數列const才可以執行。
>
> 3. p52.中間:
> ".....這情況下並不需要合成出一個default copy constructor,
> 因為上述宣告展現了"default copy semantics"........."
> 這段話應如何解釋呢?怎樣才算是default copy semantics?
> "bitwise copy semantics"?
>
> 4. p.74
> 裡面提到 member initialization list 在四種情形下可以
> 被使用(即使沒有用,也可以正確編譯,只是會造成效率不彰),
> 但LIPPMAN沒有說明為何會造成編譯器對以兩種不同方式設定初值,
> 會擴展成為不同的碼,是因為編譯器設計上某種無法避免的需要?
> 還是有其他的原因
>
> 5. LIPPMAN書中常常會列出「經過擴展、內化」或是「轉換」
> 過的原始碼,藉由觀察這些碼,可以明顯發現編譯器暗中動了
> 哪些手腳,但這似乎是本書獨有的特色,一般編譯器多提供
> 機器碼的對應,而不會列出pusedo code。不曉得這個說法
> 對不對(我現在用的是VC6)
>
> 謝謝
侯捷回覆:
> 1. 文中多次出現「內化」、「擴張」等詞(尤其在constrctor)
> 中譯本內中英對照表並未加以標註,建議你把他加進去,
> 因為這些字眼實在很少在其他書中看到。
謝謝你的建議。以下舉兩個例子。
原書 p11:
.. the likely internal transformation of the function looks as follows :
中譯本 p13:
.. 這個函式有可能被內化為:
換言之我在這裡所使用的「內化」一詞,並無直接對應的英文,
而是依上下文翻譯。
原書 p38:
.. the following two augmentations occur during compilation
中譯本 p45:
.. 下面兩個擴張行動會在編譯期間發生:
換言之這裡我所使用的「擴張」一詞,就是 augmentations。是的,
C++ 編譯器為我們加了許多碼,是一種「擴張」行為。
> 2. p.26中的程式:
> ...
> 在VC中編譯會出現轉型上的錯誤,必須拿掉參數列const才可以執行。
好的,謝謝。各家編譯器對 const 的鬆緊程度不一,
BCB4 和 G++ 對於 p.26 的程式都只給予 warning。
> 3. p52.中間:
> ".....這情況下並不需要合成出一個default copy constructor,
> 因為上述宣告展現了"default copy semantics"........."
> 這段話應如何解釋呢?怎樣才算是default copy semantics?
> "bitwise copy semantics"?
p53 中間偏下說得很清楚:
.. 什麼時候一個 class 不展現出 "bitwise copy semantics" 呢?
.. 有四種情況:
.. 1. ...
.. 2. ...
.. 3. ...
.. 4. ...
這四點以外的任何情況,便是擁有 "bitwise copy semantics"
(亦即 "default copy semantics")。
> 4. p.74
> 裡面提到 member initialization list 在四種情形下可以
> 被使用(即使沒有用,也可以正確編譯,只是會造成效率不彰),
> 但LIPPMAN沒有說明為何會造成編譯器對以兩種不同方式設定初值,
> 會擴展成為不同的碼,是因為編譯器設計上某種無法避免的需要?
> 還是有其他的原因
是因為 C++ 語言在設計上明白區分了 initialization 和 assignment
的不同。
你所謂「以兩種不同方式設定初值」,意思是:
(1) 使用 member initialization list
(2) 不使用 member initialization list,而在 ctor 中使用 assignments.
為什麼編譯器對於以兩種不同方式設定初值,會擴展成為不同的碼呢?
因為(以下節錄自《C++ Primer 中文版》p719):
--- quote ---
兩種作法...差別在於唯有 member initialization list 才
提供 class data members 的初始化行為。
而在 constructor 函式內將數值設定給 data member,其行為是一種
指派(assignment)動作。兩者差異視 data member 的型別而定。
有一個觀念很重要,那就是把 constructor 的執行想像為兩階段:
(1) 或隱喻(implicit)或明顯(explicit)的初始化階段
(initialization phase),(2) 一般化的運算階段(computation phase)。
運算階段由 constructor 函式內的所有述句組成,此階段中對任何
data members 的設定動作都被視為一個指派動作(assignment),
而不是一個初始化動作(initialization)。如果不能夠清楚區分出
其間的差異,便往往成為程式錯誤或效率不彰的來源。
初始化階段可以是隱喻的(implicit),也可以是明顯的(explicit),
視 member initialization list 是否存在而定。一個隱喻的初始化階段
會喚起所有 base class 的 default constructors(根據 base class 的宣告
次序),然後再喚起所有 member class object 的 default constructors。
--- unquote ---
> 5. LIPPMAN書中常常會列出「經過擴展、內化」或是「轉換」
> 過的原始碼,藉由觀察這些碼,可以明顯發現編譯器暗中動了
> 哪些手腳,但這似乎是本書獨有的特色,一般編譯器多提供
> 機器碼的對應,而不會列出pusedo code。不曉得這個說法
> 對不對(我現在用的是VC6)
對。
你恐怕誤會了 pusedo code 的意思。pusedo code 是意思是
以某種型式的語言表現出某些實際動作。Lippman 在本書中以
大家熟悉的 C++ 語言(是的,本書讀者應該都已熟悉了 C++ 語言)
來表現 pusedo code。事實上 C++ 編譯器當然不會為我們的碼
「擴展、內化、或轉換」出那樣的高層語言。
-- the end
--
※ Origin: 楓橋驛站<bbs.cs.nthu.edu.tw> ◆ Mail: jjhou@ccca.nctu.edu.tw
CompBook 近期熱門文章
PTT數位生活區 即時熱門文章