天天看點

c++函數傳回值與引用

對于函數的傳回值,看似簡單,但并非如此,比如:

int func(int a);該函數會傳回一個int型,如果進行一個調用int result=func(3);會發生什麼情況?

首先,func将傳回值複制到一個匿名臨時變量中,在這裡假設該臨時變量為anony(其實是沒有名字的,這裡友善闡述);然後,再将anony的值複制到result,可以看出,這裡是進行了兩次複制的。而并非一次複制。

對于傳回引用的函數:

int & func(int &a);假設該函數傳入一個int的引用,然後再func中修改它,再傳回其引用,如果調用int reslut=func(b);會發生如下情況:

傳回的是b的引用,是以相當于直接将b的值複制給了result。這裡就隻有一次複制(少了臨時變量的複制,當然也建立了一個臨時變量,隻是該臨時變量是b的一個引用)。

需要特别注意的是,按很多人的了解,這裡傳回的是一個引用,是以result就是b的引用,其實并非如此,這裡傳回引用隻是減少了一次臨時變量值的複制。如果真的要讓result能夠引用b,可以這樣做:int &result = func(b);

注:傳回普通變量的引用看不出效率的差異,但是傳回比較大的類或者結構體的時候效率差異比較明顯。

那如果是這樣申明函數int func(int a);注意,這裡傳回的不是引用。然後int &result=func(a);會發生什麼情況呢?

如果是這樣,編譯器将報錯:不能用一個臨時變量來初始化一個非常量的引用變量。

要消除這種報錯,可以這樣寫const int &result=func(a);這樣雖然傳回的不是引用,但是由于最後賦給的是一個引用變量,是以在傳回過程中也隻有一次複制過程。但是這樣的result是不能修改其引用的内容的。

還有一種看似更為詭異但卻十分合理的情況:

int &func (int &a);同樣假設該函數傳入一個int的引用,在func中修改它,然後傳回其引用。然後這樣調用func(b)=3;這樣的後果是,傳入的b的值變為3。原因是func傳回了一個b的引用,然後再将該引用賦為3,是以b的值也變成了3。

如果要禁止這種情況的發送,可以這樣聲明函數:const int &func(int &a);這樣傳回的是一個const引用,它不允許使用該引用修改其指向的值。是以如果有func(b)=3這樣的調用,将通不過編譯。

對于函數的傳回值,看似簡單,但并非如此,比如:

int func(int a);該函數會傳回一個int型,如果進行一個調用int result=func(3);會發生什麼情況?

首先,func将傳回值複制到一個匿名臨時變量中,在這裡假設該臨時變量為anony(其實是沒有名字的,這裡友善闡述);然後,再将anony的值複制到result,可以看出,這裡是進行了兩次複制的。而并非一次複制。

對于傳回引用的函數:

int & func(int &a);假設該函數傳入一個int的引用,然後再func中修改它,再傳回其引用,如果調用int reslut=func(b);會發生如下情況:

傳回的是b的引用,是以相當于直接将b的值複制給了result。這裡就隻有一次複制(少了臨時變量的複制,當然也建立了一個臨時變量,隻是該臨時變量是b的一個引用)。

需要特别注意的是,按很多人的了解,這裡傳回的是一個引用,是以result就是b的引用,其實并非如此,這裡傳回引用隻是減少了一次臨時變量值的複制。如果真的要讓result能夠引用b,可以這樣做:int &result = func(b);

注:傳回普通變量的引用看不出效率的差異,但是傳回比較大的類或者結構體的時候效率差異比較明顯。

那如果是這樣申明函數int func(int a);注意,這裡傳回的不是引用。然後int &result=func(a);會發生什麼情況呢?

如果是這樣,編譯器将報錯:不能用一個臨時變量來初始化一個非常量的引用變量。

要消除這種報錯,可以這樣寫const int &result=func(a);這樣雖然傳回的不是引用,但是由于最後賦給的是一個引用變量,是以在傳回過程中也隻有一次複制過程。但是這樣的result是不能修改其引用的内容的。

繼續閱讀