iT邦幫忙

0

C++中為什麼使用reference of local variable 是不正確的?

  • 分享至 

  • xImage

以這個例子來說

#include<iostream>
int& f(int a){
return a;}
int main(){
    int b;
    b=f(5);
    std::cout<<b;
   return 0;}

就我所知function 傳回main的temporary object跟stackframe裡的local variable 的生命週期會持續到statment的結束

也就是說
在assign f(5)給b的時候a應該還是alive的,那麼取他的reference再賦值給b,應該也沒問題,但是為什麼這個程式沒辦法順利output呢?

C++新手,謝謝大家回答

不好意思打錯,應該是在assign f(5)給b的時候「 a」應該還是alive的
已刪除
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
0
海綿寶寶
iT邦大神 1 級 ‧ 2024-04-11 22:14:29

我實在看不懂你寫的 call by reference

以下是Google Gemini寫的
https://ithelp.ithome.com.tw/upload/images/20240411/20001787vhZrSzxBWS.png

0
frogsoul
iT邦研究生 4 級 ‧ 2024-04-12 08:09:04
int& f(int a){  // a的生命週期使於此 
return a;}      // a的生命週期終於此

a是進入f之後才生出來的函式內部變數
a的5是從外面複製值進來的
外面的b還沒拿到,a就消失了

看更多先前的回應...收起先前的回應...
sam0407 iT邦大師 1 級 ‧ 2024-04-12 10:03:32 檢舉

錯字糾察隊:a的生命週期"始"於此

謝謝
但是我學到的是temporary的lifetime會持續到expression的結束(也就是b=f(5);這行)
還是我學的是錯的@@?

SunM0on iT邦新手 4 級 ‧ 2024-04-12 15:53:25 檢舉

betey20232
也不能說錯吧其實,但我會建議你,大部分時候,把參數生命週期當在大括號內就好,在C++11以後,有個東西叫Expiring Value
他是rvalue兩種中的其中一種

好的 謝謝!

1
SunM0on
iT邦新手 4 級 ‧ 2024-04-12 16:06:38

你這個問題要深究其實不太適合剛入門的新手
首先 C++11以後的lvalue rvalue出現了一點變化
其中 rvalue中可以分為兩類Expiring Value、Pure rvalue
Expiring Value是為了延續變數使用

你可以跑跑看,思考一下End3那段的結果

#include <iostream>

using namespace std;

class Apple{
public:
	Apple(){
		int *App = new int[5];
		cout << "create App malloc space." << endl;
	}
	~Apple(){
		delete [] App;
		cout << "clear App malloc space." << endl;
	}
	int *App = NULL;
};
Apple getApple(){
	Apple a;
	return a;
}

void setApple(const Apple & a){
	cout << "const reference." << endl;
}

void setApple(Apple && a){
	cout << "right value reference." << endl;
}

int main(){
	const Apple & apple = getApple();
	setApple(apple);
	cout << "End1" <<endl;
	
	Apple a;
	setApple(a);
	cout << "End2" << endl;

	setApple(getApple());
	cout << "End3" << endl;
    
    return 0;
}
/*
create App malloc space.
const reference.
End1
create App malloc space.
const reference.
End2
create App malloc space.
right value reference.
clear App malloc space.
End3
clear App malloc space.
clear App malloc space.
*/

下面這段code
setApple(getApple())
去調用的就是setApple(Apple && a)
隨後結束立即銷毀

&& 就是 rvalue reference
Expiring Value會使用的場景
主要是為了極致效能,追求不浪費資源出現的

謝謝!
題外話我發現
如果沒有
void setApple(Apple && a)

setApple(getApple());
就會呼叫
void setApple(const Apple & a)耶
這樣不會ambiguous嗎

然後
如果把第三個改成
apple&& p=getApple();
setApple(p);
他就會去呼叫
void setApple(const Apple & a)

所以這兩個是可以這樣換來換去的嗎(不好意思我對右值參照超不熟..)

SunM0on iT邦新手 4 級 ‧ 2024-04-13 14:54:44 檢舉

betey20232
第一個問題
沒有void setApple(Apple && a)的話 會建立一個臨時的Apple物件,然後只剩一個setApple 接受的是const reference,編譯器會把它當成左值
有void setApple(Apple && a)的話 會返回一個臨時的Apple物件,這個返回的物件是右值,能被編譯器識別出,所以使用rvalue reference版本的function

第二個問題
是左值 右值 左值引用 右值引用的概念
setApple(getApple());
是因為拿到的這個Apple本身是右值,所以能走rvalue reference版本的function,而你用Apple&& p=getApple();,改變了他是右值的狀態,p是右值引用,同時也是左值,而左值無法被作為右值引用使用

你想要這麼做,要利用move將p的狀態轉為右值,右值引用才能去接受這個右值,像下面這樣,但這就不是Expiring Value了

    Apple&& p=getApple();
    setApple(std::move(p));
    cout << "End4" << endl;
SunM0on iT邦新手 4 級 ‧ 2024-04-13 15:04:38 檢舉

betey20232
這個東西不能換來換去,左值只能被左值引用,同理右值引用只能接受右值,另外,右值引用本身一定是左值,所以,左值引用可以接受右值引用,都是合法的code

這個東西是真的不好理解,真的能搞懂的人又能講明白的也不多,我也有段時間沒寫C++了,建議對我說的保有質疑態度,多看資料,我能給你的只有這些關鍵字,還有這種基本概念,其他我不能確定我說的是否完全正確

我要發表回答

立即登入回答