關於c++中的臨時物件問題
**:c++中真正的臨時物件是看不見的,它們不出現在你的源**中,臨時物件的產生在如下幾個時刻:
1. 用建構函式作為隱式型別轉換函式時,會建立臨時物件。
例:class integer
~integer()
{}private:
int m_val;
};void calculate(integer itgr)
那麼語句: int i = 10;
calculate(i);
會產生乙個臨時物件,作為實參傳遞到calculate 函式中。
2. 建立乙個沒有命名的非堆(non-heap)物件,也就是無名物件時,會產生臨時物件。
如:integer& iref = integer(5); //用無名臨時物件初始化乙個引用,等價於
//integer iref(5);
integer itgr = integer(5); //用乙個無名臨時物件拷貝構造另乙個物件
按理說,c++應先構造乙個無名的臨時物件,再用它來拷貝構造itgr,由於
該臨時物件拷貝構造 itgr 後,就失去了任何作用,所以對於這種型別(只起拷貝構造另乙個物件的作用)的臨時物件,c++特別將其看做: integer itgr(5); 即直接以相同引數構造目標物件,省略了建立臨時物件這一步。
calculate( integer(5) ); //無名臨時物件作為實參傳遞給形參,函式調
//用表示式結束後,臨時物件生命期結束,被//析構.
3. 函式返回乙個物件值時,會產生臨時物件,函式中的返回值會以值拷貝的形式拷貝到被調函式棧中的乙個臨時物件。
如:integer func()
void main()
表示式 func() 處建立了乙個臨時物件,用來儲存func() 函式中返回的物件,臨時物件由 func() 中返回的 itgr 物件拷貝構造(值傳遞),臨時物件賦值給 in後,賦值表示式結束,臨時物件被析構。見下圖:
看看如下語句:
integer& iref = func();
該語句用乙個臨時物件去初始化iref 引用,一旦該表示式執行結束,臨時物件的生命週期結束,便被結束,iref引用的屍體已經不存在,接下來任何對 iref 的操作都是錯誤的。
下面,來看看實際的測試結果,**如下:
class
vector3
vector3(float
fx, float
fy, float
fz):x(0.0f),y(0.0f),z(0.0f)
vector3(const
vector3& rht)
:x(rht.x), y(rht.y), z(rht.z)
~vector3()
vector3& operator = (const
vector3& rht)
private:
float
x;float
y;float
z;};
vector3
func1()
vector3
func2()
void main()
分析:<1>.
vector3 v1 = func1();
該語句的執行過程本該是:
1>. 在 func1() 中構造乙個無名物件
2>. 由 func1() 中的無名物件拷貝構造呼叫表示式處的臨時物件
3>. 再由臨時物件拷貝構造v1
4>. func1() 返回,析構無名物件
5>. 整個語句結束,析構臨時物件
但是c++ 會優化上述過程,省略了 1>. 2>. 處的臨時物件建立,直接以
1.0f, 1.0f, 1.0f 為引數構造v1,這樣只會有一次建構函式的呼叫。結果
如圖:<2>.
v1 = func1();
該語句的執行過程本該是:
1>. 在 func1() 中構造乙個無名物件
2>. 由 func1() 中的無名物件拷貝構造呼叫表示式處的臨時物件
3>. 再由臨時物件賦值給v1 (賦值運算子)
4>. func1() 返回,析構無名物件
5>. 整個語句結束,析構臨時物件
但是c++ 會優化上述過程,省略了 1>. 處的無名臨時物件建立,直接以
1.0f, 1.0f, 1.0f 為引數構造呼叫表示式處的臨時物件,因為是賦值,所以這個臨時物件是無法被優化的,賦值完畢後,表示式結束,臨時物件被析構。結果如圖:
<3>.
vector3
v2 = func2();
該語句的執行過程本該是:
1>. func2() 中的 ret 拷貝構造呼叫表示式處的臨時物件
2>. 該臨時物件拷貝構造v2
3>. 析構臨時物件
但是c++ 會優化上述過程,省略了建立臨時物件這一步,直接由ret拷貝
構造v2,就一次拷貝建構函式的代價。
結果如圖:
<4>.
vector3
v3;v3 = func2();
執行過程如下:
1>.
構造v3
2>.
進入func2(),構造ret
3>.
返回ret,用ret拷貝構造到呼叫表示式處的臨時物件
4>. func2()
結束,ret被析構
5>.
臨時物件賦值給v3
6>.
賦值表示式結束,析構臨時物件
結果如圖:
綜上所述,可得如下結論:
<1>. 在使用乙個臨時物件( 可能是無名物件 或者 返回物件值時 ) 建立構造另乙個物件的過程的中,c++會優化掉該臨時物件的產生,直接以相同引數呼叫相關建構函式構或者 直接呼叫拷貝建構函式 到 目標物件.
<2>. 若不是物件建立,而是物件賦值,則在賦值表示式的右值處的臨時物件
建立不能省略,臨時物件賦值給左值後,表示式結束,臨時物件被析構。
C 中關於臨時量和臨時物件
一 臨時量的生成 1 內建型別產生的臨時量 常量 不可更改 2 自定義型別產生的臨時量 變數 可以更改 3 隱式產生的臨時量 常量 二 返回值 1 返回內建型別的時候,產生的都是暫存器的立即數 2 返回自定義型別的時候,也是通過暫存器返回的,但是用指標或者引用來接收返回值時,編譯器會自動產生臨時量 ...
C 中的臨時物件
我們知道在c 的建立物件是乙個費時,費空間的乙個操作。有些固然是必不可少,但還有一些物件卻在我們不知道的情況下被建立了。通常以下三種情況會產生臨時物件 1,以值的方式給函式傳參 2,型別轉換 3,函式需要返回乙個物件時 現在我們依次看這三種情況 一,以值的方式給函式傳參。我們知道給函式傳參有兩種方式...
C 中的臨時物件
1,臨時物件神秘在於不知不覺就請入程式當中,並且給程式帶來了一定的問題 2,下面的程式輸出什麼?為什麼?1 include 2 3class test411 12 test 這裡程式作者想要 復用,直接呼叫已經構造好的函式來完成沒有引數的建構函式的函式體 1316 17void print 1821...