對於乙個下面這樣的程式片段:
ta,b;tc
=a+b
;
死板一點來講,它應當產生乙個臨時物件用來儲存a+b的結果,然後以臨時對 象作為初值呼叫拷貝建構函式初始化物件c。而實際上編譯器更願意直接呼叫 拷貝建構函式的方式將a+b的值放到c中,這樣就不需要臨時物件,和它的構造 函式和拷貝建構函式的呼叫了。
更進一步,如果operator +的定義符合nrv優化的條件,那麼nrv優化的開啟, 將使得拷貝建構函式的呼叫和named object的析構函式都免了。期間詳情可 以參見」nrv優化」。也就是說對於上面那種情形在我們的**中是不產生 臨時物件的。但是對於乙個情況非常類似的賦值操作語句c = a+b
,卻有很 大的差別,那個臨時變數是不能省的
不能忽略臨時物件,反而導致如下過程:
// pseudo c++ code// t temp = a + b;
ttemp;a
.operator+(
temp,b
);// @1 [^注1]
// c = temp c.
operator=(
temp
);// @2
temp.t
::~t
();
在**@1處,表明以拷貝建構函式或nrv方式將結果儲存的臨時物件中。為什 麼不能省略那個臨時物件,比如直接這樣:
c.t::~t
();c.t
::t(a
+b);
這不是更高效,更簡潔的方式嗎?不行,其原因在於,拷貝建構函式、析構 函式以及賦值操作符都可以由使用者提供,沒有人能保證,析構函式加拷貝 建構函式的組合和賦值操作符具有相同的含義。所以:t c=a+b
總是比c = a + b
更有效率。
對於乙個沒有出現目標物件的表示式a + b
,那麼產生乙個臨時物件來儲存 運算結果,則是非常必要的。
很多時候,產生臨時物件是必不可少的,但是何時摧毀乙個臨時物件才是最 佳行為呢?過早或過晚都不太適合,過早有可能使得程式錯誤,過晚的話又 使得資源沒有得到及時**。對於下面的程式:
strings1("hello "
),s2
("world "
),s3
("by adoo"
);std
::cout
s3<<
std::
endl
;
顯然儲存s1+s2
結果的臨時物件,如果在與s3進行加法之前析構,將會帶來 **煩。於是c++標準中有一條:
完整的表示式,是指涵括的表示式中最外圍的那個。我們再看上面那個字元 串相加的表示式,當計算完成,而cout還未呼叫,此時我們析構掉儲存最終 結果的臨時物件,豈不悲劇。其實上面的規定還有兩個例外:
凡含有表示式執行結果的臨時性物件,應該儲存到object的初始化操作 完成為止。
如果臨時性物件被繫結與乙個引用,臨時物件將殘留,直至被初始化的 引用的生命結束,或直到臨時物件的生命週期結束——視哪一種情況先達 到,對應於這種情況:
::strings1(
"hello "
);::
string&s
=s1+"world"
;
侯捷認為此處為 lippman 的錯誤,他認為應該為temp.operator + ( a, b )
但我以為是侯捷並沒有理解lippman的意思,回 顧一下,《深度探索物件模型》2.3講到的返回值初始化(return value initialization)——返回值將作為乙個額外的引數提供給函式,來傳回函式內 部的值,也就是說對於乙個 operator + 操作符t t::operator+ (const t& right)
將轉化為void t::operator+ (t &result ,const t& right)
所以temp=a+b
是a.operator+( temp, b )
還是temp.operator+( a, b )
自然不言而喻。
第六章 臨時性物件
1.是否會產生乙個臨時物件,視編譯器的進取性和 操作發生時的語境而定。c 標準中指出編譯器對臨時性物件有完全的自由度。2.在新開闢的記憶體上以拷貝的方式構造物件時,幾乎所有編譯器都不會產生乙個臨時性物件。t c a b 其中加法運算子形式如下 t operator const t const t 或...
C 物件模型 臨時性物件 第六章
如果有乙個函式,形式如下 t operator const t const t 以及兩個t objects,a和b,那麼 a b 可能會導致乙個臨時性物件,以放置傳回的物件.是否會導致乙個臨時性物件,視編譯器的進取性 aggressiveness 以及上述操作發生時的程式上下關係 program c...
匿名物件?臨時物件?
關於匿名物件與臨時物件,這個概念不是絕對的,概念的區分往往十分拗口難記。要根據作用域,生存時間和用法來來決定 工作多年這些拗口的概念我從來沒有真的記住過,也沒有乙個部落格講清楚他們的區別。這裡我們參考 effective c 中得稱謂,稱之為區域性物件。但是區域性也是有範圍得。下面論證。1無名則無份...