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


轉自:

https://blog.csdn.net/qq_22660775/article/details/89854545

返回引用與返回非引用的區別:

返回引用時,函數內部不會構造一個臨時變量,而是直接將返回值返回出去。而當為非引用時,會構造一個臨時變量(但不一定),然后返回這個匿名的臨時變量。

舉例:

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;
}

  結果為:

 

 實際上這個過程是:

首先在main中生成t,調用一個默認構造函數

然后在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;
}

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM