日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++中引用和指针的不同

發布時間:2025/3/20 c/c++ 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++中引用和指针的不同 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

引用,其本質就是指針,將它用在一些特別的場合,會比指針更簡潔,更方便。具體說來,指針多用于動態內存管理和對數組的操作等,C風格的代碼接收和返回指針;引用則往往用在接收和返回類類型的名字空間域函數或類域函數,以避免類對象的復制開銷。但是請注意,引用畢竟不完全等同于指針,它們有一些差異:
  1、引用必須初始化,指針則不然。
int *pi;//可以
int &ri;//不行,未初始化
int i;int &ri=i;//可以
  2、引用不能為空引用,指針則不然。
int *pi=NULL;//可以
int *pi=NULL;int &ri=*pi;//會引發問題。
  3、引用在初始化后,不能再引用其他對象,指針則不然。
void f(int &ri)
{
??? int i=3;
??? ri=4;//改變所引用的實參
??? ri=&i;//錯誤,類型不符
??? ri=i;//ri并未轉為引用局部變量i
}
  雖然每次調用f時,都有可能會使形參ri,引用不同的實參,但是在f函數內,無法在調用處,引用初始化后,再改變其所引用的對象。顯然包括引用在內,在很多時候,初始化與賦值運算符的語義有很大區別。
  4、引用在必要時實現為指針,但是常規語法取不到這個內部指針的地址。
int i=3;int *pi=&i;//i的值為3,地址為&i;pi的值為&i,地址為&pi
int i=3;int &ri=i;//i的值為3,地址為&i;ri的值為3,地址為&i,初始化后ri和i基本為同義語。
  實際上,當引用ri初始化為i后,語言實現可能只將ri優化處理成i的別名,而不將其實現為指針;也可能使用一個內部指針來完成工作。比如第3條中的f函數的形參ri,每次具體調用函數時,都可能會傳入不同地址的實參。因為設計引用就是要避免對象復制的,因此它會壓入堆棧一個指向被引用類型的指針。有可能這樣來實現:
int i=3;
int &ri=i;//可實現為int *temp_pi=&i;以后每次源程序中使用ri時,就會被相應替換成*temp_pi
  即使實現為這樣的內部指針,也無法用正常的語法來取得它的地址。因為按照上邊的分析,初始化后,取地址操作&ri將等價于&*temp_pi。那么這對用戶來說,有什么會造成影響的不同嗎?來看看一種不太常見的情況:可變個數參數表的省略號...前一個參數,如果是引用類型,將無法正常工作;如果是指針類型或簡單類型等,則不會有問題。如有以下聲明:
void f(int i,...);
  則在實現代碼中,可以使用C標準庫的stdarg.h來取得可變個數部分的參數。有興趣的話可以去看看stdarg.h的具體代碼,它是用宏來完成的,針對不同的環境,采用了相應的手段。我用一段功能類似的偽代碼來說明一下:

void f(int i,...)//此函數用i來表示可變個數參數的個數
{
??? int ix;
??? void *base=&i;
??? for(ix=0;ix<i;ix++)
??? {
??????? base+=sizeof(int);//或者依實現為base-=sizeof(int)
??????? cout<<"第"<<ix+1<<"個int參數的值為:";
??????? cout<<*((int *)base)<<endl;
??? }
}
?
  如果有調用f(5,1,2,3,4,5);則5,4,3,2,1,5將從右到左依次被壓入堆棧,然后調用f函數。在f函數內部來看,那幾個未命名的可變參數,是每個占一個sizeof(int)大小,一個接一個挨著放在堆棧上的,并且局部變量i指向了堆棧頂的位置。這時可以用相對于堆棧頂位置的位移量來取得每一個局部變量。當函數返回時,由調用點來清理堆棧。這樣,f(5,1,2,3,4,5);和f(3,10,11,12);均可正確調用和返回,因為每處調用均知道自己用了幾個參數,所以它可以在函數返回后,正確地在堆棧上彈出參數(其缺點就是每處調用都要自己清理,這樣方式的程序長度,要比清理只出現在被調函數返回處的方式,要長一些)。這就是所謂的cdecl調用約定。然而,如果...前的參數為引用類型,如:
void f(const int &ri,...);//如果使用非左值進行調用,引用必須為const
調用f(5,1,2,3,4,5)將會發生什么呢?
因為int &ri是個引用參數,所以實際上會是:
push 5;
push 4;
push 3;
push 2;
push 1;
const int temp_i=5;
const int *temp_pi=&temp_i;
push temp_pi;
  也就是說,和5個可變個數參數并排挨著的實參ri,在實際調用時,會被處理成向堆棧壓進一個const int *類型的地址值。那么在f函數內的代碼中,void *base=&ri;又將指向何處呢?按前面的分析,&ri會被處理成&*temp_pi,其結果就是temp_pi的值,temp_i的地址。試圖取回和1、2、3、4、5挨著的這個內部指針的地址,其結果卻是內部指針temp_pi的值,temp_i的地址,它并不在可變個數參數的1、2、3、4、5中1的旁邊。所以調用將無法正常取得...部分的參數。

發表于 @ 2009年03月01日 14:19:00 | 評論( 0 ) | 編輯| 舉報| 收藏

新一篇:精解C++的switch語句

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/myliupp/archive/2009/03/01/3947023.aspx

總結

以上是生活随笔為你收集整理的C++中引用和指针的不同的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。