幾乎所有C++的書籍中都強烈建議函數返回的時候,要使用按引用返回、甚至直接返回指標,尤其是涉及到class和struct的時候。
如果函數返回對象,而不是指標,那麼在執行return的時候,會使用被return的對象“複製構造”臨時對象,然後,return語句執行完畢(遇到分號;了)函數內部建立的全部變數析構、出棧。而被“賦值構造”的臨時對象則在調用該函數的語句執行完畢(遇到分號;或者右邊的大括弧})後,析構。
上代碼:
class CpCls{public:CpCls(int){cout<<"CpCls(int)"<<endl;}//private://CpCls c2=1;時,若將複製建構函式設定為private,則G++編譯失敗CpCls(const CpCls&){cout<<"CpCls(CpCls&)"<<endl;}};/*該函數在執行時,會產生兩個CpCls類型的臨時變數:**1、傳回值臨時變數T1(就是在函式宣告最開始的地方,那個聲明傳回值類型為CpCls的地方)**2、return語句執行時的臨時變數T2(CpCls(1)語句會產生一個CpCls類型的臨時變數)****當執行return的時候,先產生臨時變數T2,**然後使用T2,通過拷貝建構函式,產生臨時變數T1**(如果你不信,可以把CpCls的複製建構函式設定成private的,**然後編譯就報錯了~)**return語句執行到分號;後,語句執行完畢,開始析構臨時變數T2,**函數returnPrivateCC()執行完畢後,**開始解構函式內部建立的變數(不包括臨時變數T1,**因為臨時變數T1不是在函數returnPrivateCC()中建立的,**它是在調用函數returnPrivateCC()的語句中建立的,**也就是在CpCls c3=returnPrivateCC();中建立的,**只有那條語句執行完畢,臨時變數T1才會被析構)。*/CpCls returnPrivateCC(){return CpCls(1);/*如果CpCls的複製建構函式為private,則編譯出錯!*/}void test16(){//C++中的初始化方式只有兩種:直接初始化,複製初始化//直接初始化,使用特定的建構函式初始化CpCls c1(1);/*複製初始化,使用=符號初始化**在G++中,首先使用1建立CpCls的臨時對象,**然後使用這個臨時對象調用複製建構函式初始化c2**儘管這個過程隨後會被G++最佳化成直接使用CpCls(int)初始化c2****在VS2005中,直接使用CpCls(int)初始化c2****G++和VS2005的執行結果一樣,這是編譯器最佳化的原因,**如果將複製建構函式的訪問限制設定為private,則G++編譯失敗*/CpCls c2=1;/*如果函數返回的是對象而非指標或引用,**則return後面跟的值會被通過調用複製構造的方式初始化臨時變數**此時,如果複製建構函式是private,則編譯失敗****函數returnPrivateCC()的傳回值類型是CpCls,指的是函數的傳回值會**被存放在CpCls類型的臨時變數中,然後函數中建立的CpCls變數會在函數**執行結束後析構,而CpCls類型的臨時變數則在語句CpCls c3=returnPrivateCC();**執行結束後被析構*/CpCls c3=returnPrivateCC();}
總結一句:
臨時變數的生存範圍是語句級——分號;結束或者右邊的大括弧}結束。語句結束之後,臨時變數就被析構了~