C++中爲什麼引用可以作爲函數返回值?
本文背景
在程序設計與算法(三)第01周測驗003:好怪異的返回值裏面,題目的解答是這樣子的:
#include <iostream>
using namespace std;
int & getElement(int * a, int i)
{
return a[i];
}
int main()
{
int a[] = {1,2,3};
getElement(a,1) = 10;
cout << a[1] ;
return 0;
}
有讀者奇怪的是,爲什麼int & getElement(int * a, int i)
要加&
,直接int getElement(int * a, int i)
不可以麼?
真機測試
那我們在CLion
裏不加&
試試。
#include <iostream>
using namespace std;
int getElement(int * a, int i)//不加&
{
return a[i];
}
int main()
{
int a[] = {1,2,3};
getElement(a,1) = 10;
cout << a[1] ;
return 0;
}
調試信息
調試,返回錯誤:
====================[ Build | test1 | Debug ]===================================
/opt/clion/bin/cmake/linux/bin/cmake --build /home/mrcangye/CLionProjects/test1/cmake-build-debug --target test1 -- -j 2
[ 50%] Building CXX object CMakeFiles/test1.dir/main.cpp.o
/home/mrcangye/CLionProjects/test1/main.cpp: In function ‘int main()’:
/home/mrcangye/CLionProjects/test1/main.cpp:12:20: error: lvalue required as left operand of assignment
12 | getElement(a,1) = 10;
| ^~
make[3]: *** [CMakeFiles/test1.dir/build.make:63: CMakeFiles/test1.dir/main.cpp.o] Error 1
make[2]: *** [CMakeFiles/Makefile2:76: CMakeFiles/test1.dir/all] Error 2
make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/test1.dir/rule] Error 2
make: *** [Makefile:118: test1] Error 2
調試信息指出了程序第12行,getElement(a,1) = 10;
出現錯誤。
這也是接下來需要講述的問題。
參考資料
爲了解決這個問題,我拿出了C++ Primer Plus 第六版中文版 人民郵電出版社2012年七月第一版,2019年1月北京第31次印刷版本,第8章 函數探幽 第268頁
基本原理
重點在於:
getElement(a,1) = 10;
這是一個賦值語句
在賦值語句中,語句左邊,也就是=
號左邊,必須是可以修改的值,深入瞭解一下,必須是一個可以修改的內存塊。重點是這個等號左邊的值必須是可以修改的。
常規(非引用)的返回類型是放在=
右邊的,是不能通過地址訪問的值。不可以出現在=
號左邊。
爲什麼呢?因爲常規的返回值是存在臨時內存單元中的,運行到下一條語句時,這個返回值就不存在了。return
後面的表達式將結果的值計算出來,然後這個值被複制到一個臨時位置,返回給調用函數,調用函數再到臨時位置使用這個值
解答
上面的原理和調試出錯的信息是一致的。
如果我們不加&
,那麼返回的是一個確切的int
數值1
,1 = 10
是不符合左邊可以修改的值的要求。
爲了符合這個要求,我們就需要加&
號,使得這個函數getElement(a,1)
返回值是int &
,並將int &
返回,就是:a[1] = 10
,這樣就合法了