| 導購 | 订阅 | 在线投稿
分享
 
 
 

對C++中引用的補充說明(實例)

來源:互聯網  2008-06-01 02:03:44  評論

#include <iostream>

#include <string>

using namespace std;

void main(int argc,char* argv[])

{

int a=10;

int b=20;

int &rn=a;

cout<<rn<<""<<a<<endl;

cout<<&rn<<""<<&a<<endl;//c++中是無法取得應用的內存地址的,取引用的地址就是取目標的地址!

rn=b;//把引用指向另一個目標----變量b

cout<<&rn<<""<<&a<<""<<&b<<endl;

rn=100;//試圖改變b的值

cout<<a<<""<<b<<endl;//輸出修改後的結果

cin.get();

}

由于引用本身就是目標的一個別名,引用本身的地址是一個沒有意義的值,所以在c++中是無法取得引用的內存地址的。取引用的地址就是取目標的地址,c++本身就根本不提供獲取引用內存地址的方法。

引用一單初始化,就不在能夠被指向其它的目標,雖然編譯不會出錯,但操作是不起作用的,實際上還是指向最先指向的目標。

上面代碼中的rn=b實際在計算機看來就是a=b,所以修改的還是a的值。#include <iostream>

#include <string>

using namespace std;

void main(int argc,char* argv[])

{

int a=10;

void &rn=a;// 錯誤的,void即無類型的類型

int a[100];

int &ra[100]=a;//錯誤,不能聲明引用數組

cin.get();

}上面的兩錯誤要記住引用的特性,void修飾是不能夠聲明引用的,引用是不能夠聲明數組的,即不能夠聲明引用數組。


對C++中引用的補充說明(實例)
更多內容請看C/C++技術專題 C/C++應用實例專題,或

下面我們要說一下,也是補充中最重要最需要把握的內容,也是對傳統函數操作的內存狀態的一個補充學習。下面我們來看一個例子:

#include <iostream>

#include <string>

using namespace std;

float c;

float test(float,float);

void main(int argc,char* argv[])

{

float pn=test(3.0f,1.2f);

cout<<pn;

cin.get();

}

float test(float a,float b)

{

c=a*b;

return c;

}在上面的代碼中我們可能我們可能以爲函數返回的就是c變量,呵呵。這麽想可能就錯了,普通情況下我們在函數內進行普通值返回的時候在內存棧空間內其實是自動産生了一個臨時變量temp,它是返回值的一個副本一個copy,函數在return的時候其實是return的這個臨時産生的副本。

數據在內存中的情況如下圖:

對C++中引用的補充說明(實例)
上圖明確表示了副本領事變量的情況。


對C++中引用的補充說明(實例)
更多內容請看C/C++技術專題 C/C++應用實例專題,或

下面我們再來看一種情況,就是把返回值賦給引用:

#include <iostream>

#include <string>

using namespace std;

float c;

float test(float,float);

void main(int argc,char* argv[])

{

float &pn=test(3.0f,1.2f);//警告:返回的將是臨時變量,pn引用將成爲臨時變量的別名!

cout<<pn;

cin.get();

}

float test(float a,float b)

{

c=a*b;

return c;

}float &pn=test(3.0f,1.2f);這句在bc中能夠編譯通過,因爲bc擴展設置爲臨時變量設置引用,那麽臨時變量的生命周期將和引用的生命周期一致,但在vc中卻不能通過編譯,因爲一但test()執行過後臨時變量消失在棧空間內,這時候pn將成爲一個沒有明確目標的引用,嚴重的時候會導致內存出錯。它在內存中的情況見下圖:

對C++中引用的補充說明(實例)
我們在圖中看到,由于函數仍然是普通方法返回,所以仍然會有一個副本臨時變量産生,只不過,這一次只是返回一個目標地址,在main中目標地址被賦予了引用pn。


對C++中引用的補充說明(實例)
更多內容請看C/C++技術專題 C/C++應用實例專題,或

下面我們再看一種情況,這是返回引用給變量的情況:

#include <iostream>

#include <string>

using namespace std;

float c;

float& test(float,float);

void main(int argc,char* argv[])

{

float pn=test(3.0f,1.2f);

cout<<pn;

cin.get();

}

float &test(float a,float b)

{

c=a*b;

return c;

}這種返回引用給變量的情況下,在內存中,test()所在的棧空間內並沒有産生臨時變量,而是直接將全局變量c的值給了變量pn,這種方式是我們最爲推薦的操作方式,因爲不産生臨時變量直接賦值的方式可以節省內存空間提高效率,程序的可讀性也是比較好的。

它在內存中的情況見下圖:

對C++中引用的補充說明(實例)


對C++中引用的補充說明(實例)
更多內容請看C/C++技術專題 C/C++應用實例專題,或

最後的一種情況是函數返回引用,並且發值賦給一個引用的情況:

#include <iostream>

#include <string>

using namespace std;

float c;

float& test(float,float);

void main(int argc,char* argv[])

{

float &pn=test(3.0f,1.2f);

cout<<pn;

cin.get();

}

float &test(float a,float b)

{

c=a*b;

return c;

}這種情況同樣也不産生臨時變量,可讀和性能都很好,但有一點輕易弄錯,就是當c是非main的局部變量或者是在堆內存中臨時開辟後來又被fee掉了以後的區域,這種情況和返回的指針是局部指針的後果一樣嚴重,會導致引用指向了一個不明確的地址,這種情況在內存中情況見下圖:

對C++中引用的補充說明(實例)
由于這種情況存在作用域的問題,故我們推薦采用第三種方式處理。


對C++中引用的補充說明(實例)
更多內容請看C/C++技術專題 C/C++應用實例專題,或

接下來我們說幾個利用引用作爲左值參與計算的例子,這一點一非常重要,對于理解返回引用的函數是非常有幫助的。

#include <iostream>

#include <string>

using namespace std;

float c;

float& test(float,float);

void main(int argc,char* argv[])

{

float &pn=test(3.0f,1.2f);

cout<<pn<<endl;

test(3.0f,1.2f)=12.1;//把函數作左值進行計算!

cout<<pn;

cin.get();

}

float &test(float a,float b)

{

c=a*b;

return c;

}通常來說函數是不能作爲左值,因爲引用可以做爲左值,所以返回引用的函數自然也就可以作爲左值來計算了。在上面的代碼中:

float &pn=test(3.0f,1.2f);

進行到這裏的時候pn已經指向到了目標c的地址了。

接下來運行了

test(3.0f,1.2f)=12.1;

把函數作左值進行計算,這裏由于test是返回引用的函數,其實返回值返回的地址就是c的地址,自然c的值就被修改成了12.1。

對C++中引用的補充說明(實例)
更多內容請看C/C++技術專題 C/C++應用實例專題,或

#include <iostream> #include <string> using namespace std; void main(int argc,char* argv[]) { int a=10; int b=20; int &rn=a; cout<<rn<<""<<a<<endl; cout<<&rn<<""<<&a<<endl;//c++中是無法取得應用的內存地址的,取引用的地址就是取目標的地址! rn=b;//把引用指向另一個目標----變量b cout<<&rn<<""<<&a<<""<<&b<<endl; rn=100;//試圖改變b的值 cout<<a<<""<<b<<endl;//輸出修改後的結果 cin.get(); }   由于引用本身就是目標的一個別名,引用本身的地址是一個沒有意義的值,所以在c++中是無法取得引用的內存地址的。取引用的地址就是取目標的地址,c++本身就根本不提供獲取引用內存地址的方法。   引用一單初始化,就不在能夠被指向其它的目標,雖然編譯不會出錯,但操作是不起作用的,實際上還是指向最先指向的目標。   上面代碼中的rn=b實際在計算機看來就是a=b,所以修改的還是a的值。#include <iostream> #include <string> using namespace std; void main(int argc,char* argv[]) { int a=10; void &rn=a;// 錯誤的,void即無類型的類型 int a[100]; int &ra[100]=a;//錯誤,不能聲明引用數組 cin.get(); }  上面的兩錯誤要記住引用的特性,void修飾是不能夠聲明引用的,引用是不能夠聲明數組的,即不能夠聲明引用數組。 [url=/bbs/detail_1785273.html][img]http://image.wangchao.net.cn/it/1323424048971.gif[/img][/url] 更多內容請看C/C++技術專題 C/C++應用實例專題,或   下面我們要說一下,也是補充中最重要最需要把握的內容,也是對傳統函數操作的內存狀態的一個補充學習。  下面我們來看一個例子: #include <iostream> #include <string> using namespace std; float c; float test(float,float); void main(int argc,char* argv[]) { float pn=test(3.0f,1.2f); cout<<pn; cin.get(); } float test(float a,float b) { c=a*b; return c; }  在上面的代碼中我們可能我們可能以爲函數返回的就是c變量,呵呵。這麽想可能就錯了,普通情況下我們在函數內進行普通值返回的時候在內存棧空間內其實是自動産生了一個臨時變量temp,它是返回值的一個副本一個copy,函數在return的時候其實是return的這個臨時産生的副本。   數據在內存中的情況如下圖:[url=/bbs/detail_1785273.html][img]http://image.wangchao.net.cn/it/1323424049015.gif[/img][/url]  上圖明確表示了副本領事變量的情況。 [url=/bbs/detail_1785273.html][img]http://image.wangchao.net.cn/it/1323424049075.gif[/img][/url] 更多內容請看C/C++技術專題 C/C++應用實例專題,或   下面我們再來看一種情況,就是把返回值賦給引用: #include <iostream> #include <string> using namespace std; float c; float test(float,float); void main(int argc,char* argv[]) { float &pn=test(3.0f,1.2f);//警告:返回的將是臨時變量,pn引用將成爲臨時變量的別名! cout<<pn; cin.get(); } float test(float a,float b) { c=a*b; return c; }  float &pn=test(3.0f,1.2f);這句在bc中能夠編譯通過,因爲bc擴展設置爲臨時變量設置引用,那麽臨時變量的生命周期將和引用的生命周期一致,但在vc中卻不能通過編譯,因爲一但test()執行過後臨時變量消失在棧空間內,這時候pn將成爲一個沒有明確目標的引用,嚴重的時候會導致內存出錯。  它在內存中的情況見下圖:[url=/bbs/detail_1785273.html][img]http://image.wangchao.net.cn/it/1323424049094.gif[/img][/url]  我們在圖中看到,由于函數仍然是普通方法返回,所以仍然會有一個副本臨時變量産生,只不過,這一次只是返回一個目標地址,在main中目標地址被賦予了引用pn。 [url=/bbs/detail_1785273.html][img]http://image.wangchao.net.cn/it/1323424049137.gif[/img][/url] 更多內容請看C/C++技術專題 C/C++應用實例專題,或   下面我們再看一種情況,這是返回引用給變量的情況: #include <iostream> #include <string> using namespace std; float c; float& test(float,float); void main(int argc,char* argv[]) { float pn=test(3.0f,1.2f); cout<<pn; cin.get(); } float &test(float a,float b) { c=a*b; return c; }  這種返回引用給變量的情況下,在內存中,test()所在的棧空間內並沒有産生臨時變量,而是直接將全局變量c的值給了變量pn,這種方式是我們最爲推薦的操作方式,因爲不産生臨時變量直接賦值的方式可以節省內存空間提高效率,程序的可讀性也是比較好的。   它在內存中的情況見下圖:[url=/bbs/detail_1785273.html][img]http://image.wangchao.net.cn/it/1323424049164.gif[/img][/url] [url=/bbs/detail_1785273.html][img]http://image.wangchao.net.cn/it/1323424049250.gif[/img][/url] 更多內容請看C/C++技術專題 C/C++應用實例專題,或   最後的一種情況是函數返回引用,並且發值賦給一個引用的情況: #include <iostream> #include <string> using namespace std; float c; float& test(float,float); void main(int argc,char* argv[]) { float &pn=test(3.0f,1.2f); cout<<pn; cin.get(); } float &test(float a,float b) { c=a*b; return c; }  這種情況同樣也不産生臨時變量,可讀和性能都很好,但有一點輕易弄錯,就是當c是非main的局部變量或者是在堆內存中臨時開辟後來又被fee掉了以後的區域,這種情況和返回的指針是局部指針的後果一樣嚴重,會導致引用指向了一個不明確的地址,這種情況在內存中情況見下圖:[url=/bbs/detail_1785273.html][img]http://image.wangchao.net.cn/it/1323424049263.gif[/img][/url]  由于這種情況存在作用域的問題,故我們推薦采用第三種方式處理。 [url=/bbs/detail_1785273.html][img]http://image.wangchao.net.cn/it/1323424049295.gif[/img][/url] 更多內容請看C/C++技術專題 C/C++應用實例專題,或   接下來我們說幾個利用引用作爲左值參與計算的例子,這一點一非常重要,對于理解返回引用的函數是非常有幫助的。 #include <iostream> #include <string> using namespace std; float c; float& test(float,float); void main(int argc,char* argv[]) { float &pn=test(3.0f,1.2f); cout<<pn<<endl; test(3.0f,1.2f)=12.1;//把函數作左值進行計算! cout<<pn; cin.get(); } float &test(float a,float b) { c=a*b; return c; }  通常來說函數是不能作爲左值,因爲引用可以做爲左值,所以返回引用的函數自然也就可以作爲左值來計算了。  在上面的代碼中: float &pn=test(3.0f,1.2f);   進行到這裏的時候pn已經指向到了目標c的地址了。   接下來運行了 test(3.0f,1.2f)=12.1;   把函數作左值進行計算,這裏由于test是返回引用的函數,其實返回值返回的地址就是c的地址,自然c的值就被修改成了12.1。 [url=/bbs/detail_1785273.html][img]http://image.wangchao.net.cn/it/1323424049328.gif[/img][/url] 更多內容請看C/C++技術專題 C/C++應用實例專題,或
󰈣󰈤
 
 
 
>>返回首頁<<
 
 
 
 
 熱帖排行
 
王朝網路微信公眾號
微信掃碼關註本站公眾號 wangchaonetcn
 
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有