c 返回乙個物件 使用C 臨時物件的後果

2021-10-13 18:42:19 字數 2135 閱讀 6890

但是!我就是想看看這麼做的糟糕後果是什麼!

先要搞清楚什麼是臨時物件,這裡我參考 《more effective c++》99頁定義。真正的臨時物件是在原始碼中不可見的,是棧上的、沒有名字的物件。與函式內定義的臨時物件有根本差別。

第一種:當觸發隱式型別轉換時

例如:

// 統計ch在str**現的次數

size_t counterchar(const string& str, char ch);

char cs = "123";

cout << counterchar(cs, '1') << endl;

此時,char 隱式轉換為 string,再引用為str。該隱式轉換的string,會在counterchar返回時銷毀。

第二種:當函式返回乙個物件的時候

例如:

const number operator+(const number& lhs, const number& rhs);
在函式返回時,會產生乙個臨時物件作為返回值(當然編譯器會幫你優化它,所以不一定有乙個臨時物件生成和銷毀)。

物件的類實現為:

class cat 

cat(const cat& cat)

void sleep() const

~cat()

};

很簡單,為了看清現象打了一些日誌。

情況一(正常情況):函式使用值返回,同樣拷貝賦值來儲存函式返回值。

cat foo1() 

int main()

下面來觀察執行結果:

new cat a

new cat b

copy

destroy cat b

destroy cat a

sleep b

end main

destroy cat b

簡單解釋一下:foo1執行到return b時,會執行一次拷貝建構函式。此時,main函式的c物件構造完成。之後會將兩個區域性物件銷毀。

情況二:函式返回值為引用型

cat& foo1() 

在vs的debug模式中,會先執行函式區域性物件的銷毀,再返回這個區域性物件的引用。之後呼叫cat的拷貝建構函式。由於引用的物件已經被銷毀。故會報錯

再release模式中,現象很神奇:

new cat a

new cat b

destroy cat b

destroy cat a

copy

sleep

end main

destroy cat

也就是說,物件c為雖然執行了拷貝建構函式,但並沒有複製name成員。導致物件c的name未知。

情況三:引用函式的返回物件

cat foo1() 

int main()

在debug模式下,現象與情況一相同,變數c引用的是乙個匿名物件。

new cat a

new cat b

copy

destroy cat b

destroy cat a

sleep b

end main

destroy cat b

在release模式下,很有意思

new cat a

new cat b

destroy cat a

sleep b

end main

destroy cat b

由於編譯器的優化,foo函式區域性變數b真的被main函式區域性變數c所引用了,其記憶體釋放也是在main函式返回時完成的。

不要試圖使用"引用"來減少構造和析構函式的呼叫。如果你非要優化的話,建議使用返回值優化(rvo)。

cat foo2()

如此一來,main函式中的變數c就不會呼叫拷貝構造了。

c 返回乙個物件

當函式返回類物件的時候,c 編譯器會進行返回值優化 返回值優化 return value optimization,縮寫為rvo 是c 的一項編譯優化技術。即刪除保持函式返回值的臨時物件。這可能會省略兩次複製建構函式,即使複製建構函式有 1 2 典型地,當乙個函式返回乙個物件例項,乙個臨時物件將被建...

C 臨時物件

臨時物件的產生 1.用建構函式作為隱式型別轉換函式時。2.建立乙個沒有名字的物件時。直接寫下 ctempobj 輸出 init obj exit obj 不單調用了建構函式,還呼叫了析構函式.既然是物件也可以這樣使用 ctempobj fun 不過這樣使用可要小心了 new ctempobj fun...

C 臨時物件

c 中有這樣一種物件 它在 中看不到,但是確實存在。它就是臨時物件 由編譯器定義的乙個沒有命名的非堆物件 non heap object 為什麼研究臨時物件?主要是為了提高程式的效能以及效率,因為臨時物件的構造與析構對系統效能而言絕不是微小的影響,所以我們應該去了解它們,知道它們如何造成,從而盡可能...