繼續整理第六章剩下的內容,關於臨時對象的幾條準則。
1. 在某些情況下,編譯器可以產生必要的,或者可以帶來方便的臨時對象,具體行為由編譯器來定義。例如,對於如下操作:
T a, b;T c = a + b;//T operator+ (const T&, const T&)
a. 編譯器會產生一個臨時對象,放置a+b的結果,然後使用T的拷貝建構函式,把臨時對象當作c的初始值。
b. 另外一種比較可能的方式是直接以拷貝構造的方式將a+b的值放到c中,代碼類似於這樣:T c( a + b ),這樣就避免了臨時對象的構造和析構成本。
c. 此外,如果RVO(傳回值最佳化)生效,可以直接在c中求運算式的結果,不再需要拷貝構造。
對於以上三種方式C++是沒有明確標準的,而是留有一定的自由度。
由於編譯器市場競爭的關係,很多編譯器在對以上運算式不會產生臨時對象,然而對於賦值構造運算式,卻無法避免臨時對象產生,所以T c = a + b要比T c; c = a+ b高效:
T a, b;T c;c = a + b;
2.
臨時對象的銷毀,應該在完整運算式求值過程中的最後一步,該運算式造成了臨時對象的產生。也就是說,如果一個運算式導致了臨時對象的產生,那麼這(些)臨時對象需要運算式完全執行完之後才能銷毀,例如:
((objA > 1024) && (objB > 1024)) ? objA + objB : foo(objA, objB);
一共有五個子算式,內帶在一個問號運算式中,任何一個子運算式所產生的任何一個臨時對象,都應該在完整運算式被求值完成後才可以毀去。
3. 凡是含有運算式執行結果的臨時性對象,應該保留到object的初始化操作完成為止,例如:
T c = isTrue? 0 : a + b;
a+b產生的臨時對象必須保留到c被初始化完成為止。
4. 如果一個臨時性對象被綁定於一個引用(reference),該臨時對象需要保持到由之初始化的引用對象生命結束,或者臨時對象的生命週期結束,具體視哪一種情況先發生。例如:
const std::string& space = " ";
會產生這樣的程式碼:
std::string temp;temp.std::string::string(" ");const std::string& space = temp;t emp的生命週期必須在space活躍期間保持。
第六章的內容整理完畢,之後會繼續整理第七章也是書本的最後一章節的內容。