但是臨時變量在哪?
最后將臨時變量中的值賦值給ret
圖:
所有的傳值返回都會生成一個拷貝
便于理解,看一下匯編:
看第四句話,這里是說,把 eax 中的值,拷貝到 ret 中。
而再函數(shù)調(diào)用返回時:
這里是將 c 的值放到 eax 中的。
這也就印證了返回時,是以臨時拷貝形式返回的,由于返回值是 int ,所以是直接用的 eax 寄存器。
而不論這個函數(shù)結(jié)束后,返回的那個值會不會被銷毀,都會創(chuàng)建臨時變量返回,例如這段代碼 :
int fun()
{
static int n = 0;
n++;
return n;
}
int main()
{
int ret = fun();
cout << ret << endl;
return 0;
}
對于該函數(shù),編譯器仍然是創(chuàng)建臨時變量返回;因為編譯器不會對其進行特殊處理。
看一下匯編:
仍然是放到 eax 寄存器中返回的。
埋個伏筆:你覺不覺的這個臨時變量創(chuàng)建的很冤枉,明明這塊空間一直存在,我卻依然創(chuàng)建臨時變量返回了?能不能幫它洗刷冤屈。
如果我改成引用返回會發(fā)生什么情況嗎?
int& add(int a, int b)
{
int c = a + b;
return c;
}
int main()
{
int ret = add(1, 2);
cout << ret << endl;
return 0;
}
引用返回就是不生成臨時變量,直接返回 c 的引用。而這里產(chǎn)生的問題就是 非法訪問 。
造成的問題:
- 存在非法訪問,因為 add 的返回值是 c 的引用,所以 add 棧幀銷毀后,會訪問 c 位置空間,而這是讀操作,不一定檢查出來,但是本質(zhì)是錯的。
- 如果 add 函數(shù)棧幀銷毀,空間被清理,那么取 c 值時取到的就是隨機值,取決于編譯器的決策。
ps:雖然vs銷毀棧幀沒有清理空間數(shù)據(jù),但是會二次覆蓋
來看個有意思的:
例如這里,當(dāng)調(diào)用 add 函數(shù)之后,返回 c 的引用,接收返回值是用的ret相當(dāng)于是 c 的引用,這時由于沒有清理棧幀數(shù)據(jù),所以打印3;
但是第二次調(diào)用,重新建立棧幀,由于棧幀大小相同,第二次建立棧幀可能還是在原位置,之前空間的數(shù)據(jù)被覆蓋,繼續(xù)運算,但是此時,ret 那塊空間的值就被修改了,而這時沒有接收返回值,但是原先的那塊 c 的值被修改,所以打印出來 ret 是 30 。
所以使用引用返回時,一旦返回后,返回值的空間被修改,那么都可能會造成錯誤,使用要小心!
引用返回有一個原則:如果函數(shù)返回時,出了函數(shù)作用域,如果返回對象還在(還沒還給系統(tǒng)),則可以使用引用返回,如果已經(jīng)還給系統(tǒng)了,則必須使用傳值返回。
它倆的區(qū)別就是一個生成拷貝,一個不生成拷貝。
而這時 static 修飾的靜態(tài)變量不委屈了:
int& fun()
{
static int n = 0;
n++;
return n;
}
因為 static 修飾的變量在靜態(tài)區(qū),出了作用域也存在,這時就可以引用返回。
我們可以理解引用返回也有一個返回值,但是這個返回值的類型是 int& ,中間并不產(chǎn)生拷貝,因為返回的是別名。這就相當(dāng)于返回的就是它本身。
有時引用返回可以發(fā)揮出意想不到的結(jié)果:
typedef struct Array
{
int a[N];
int size;
}AY;
int& PostAt(AY& ay, int i)
{
assert(i < N);
return ay.a[i];
}
int main()
{
AY ay;
PostAt(ay, 1);
// 修改返回值
for (int i = 0; i < N; i++)
{
PostAt(ay, i) = i * 3;
}
for (int i = 0; i < N; i++)
{
cout << PostAt(ay, i) << ' ';
}
return 0;
}
由于PostAt 的形參 ay 為 main 中 局部變量 ay的別名,所以 ay 一直存在;這時可以使用引用返回。
引用返回 減少了值拷貝 ,不比將其拷貝到臨時變量中返回;并且由于是引用返回,我們也可以 修改返回對象 。
總結(jié)提煉:如果出了作用域,返回變量(靜態(tài),全局,上一層棧幀,malloc等)仍然存在,則可以使用引用返回。
-
C語言
+關(guān)注
關(guān)注
180文章
7604瀏覽量
136692 -
C++
+關(guān)注
關(guān)注
22文章
2108瀏覽量
73620 -
面向?qū)ο?/span>
+關(guān)注
關(guān)注
0文章
64瀏覽量
9983
發(fā)布評論請先 登錄
相關(guān)推薦
評論