轉自:面試
https://blog.csdn.net/qq_22660775/article/details/89854545函數
返回引用與返回非引用的區別:this
返回引用時,函數內部不會構造一個臨時變量,而是直接將返回值返回出去。而當爲非引用時,會構造一個臨時變量(但不必定),而後返回這個匿名的臨時變量。.net
舉例:對象
class B { public: B(){ cout << "B的構造函數" << endl; } B(int i){ cout << "帶int型參數的B的構造函數" << endl; } B(const B &ano){ cout << "B的拷貝構造函數" << endl; } B& operator=(const B& rhs){ cout << "B的賦值操做符" << endl; return *this; } virtual ~B(){ cout << "B的析構函數" << endl; } }; B func2() { B b; return b; } int main() { B t; t=func2(); //B z=func2(); cout<<endl; }
結果爲:blog
實際上這個過程是:get
首先在main中生成t,調用一個默認構造函數class
而後在func2()中生成一個b,調用一個默認構造函數效率
而後要返回b了,使用拷貝構造,利用b拷貝構造一個臨時變量tmp變量
而後析構b
而後利用tmp賦值給t
最後析構這個臨時變量tmp
能夠看到,整個過程,因爲使用的是非引用,所以會首先調用拷貝構造構造臨時變量tmp,而後返回這個tmp
而當調用B z=func2()時:
首先進入func2,對b進行構造
但這裏沒有構造臨時變量,因爲外面是B z=func2(),其實是直接將這個z傳入,而後利用b來拷貝構造這個z,最後再析構b
注意這裏析構的順序,在上面看到,構造完臨時變量tmp後,b直接就析構了,而後tmp賦值給t後tmp才析構。注意這裏b的析構時間和上一行的析構時間:
上一行是利用b構造完z後b才析構,也就是說其實是將這個z當作tmp來拷貝構造。
而最前面是先拷貝構造tmp,而後b立刻析構,最後用tmp來給b賦值。
也就是說:
若是返回的是非引用,並不必定會構造一個臨時變量。
若是使用B z=func2()這種方式是不會生成臨時變量的;但B b;b=func2();是會生成臨時變量的。
想到上次去網易面試時考官問個人一個問題:
這個返回的ans怎麼提升效率?
若是用引用返回的話則會出問題,由於返回的是局部對象,在賦值的時候實際上已經析構了。
當時的回答是將結果做爲參數放入func()中,也就是改寫爲void func(vector<int>& result);而後這樣就能夠提升效率
但面試官應該想讓我get到另外的點
難道是移動語義或者完美轉發?這個我還沒看,須要好好研究下。
vector<int> func() { vector<int> ans(2,1); return ans; }