C++返回值的引用與非引用

轉自:面試

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;
}
相關文章
相關標籤/搜索