感覺自己很廢,很懶。不懂得東西模棱兩可就過去了,廢物,垃圾。現在的知識盲區大了吧!大家敬請鄙視我吧!
故事是這樣的:
#include<stdio.h>
void change1 (int *a,int *b)
{
int c;
c=*a;
*a=*b;
*b=c;
}
void change2 (int &m,int &n)
{
int c;
c=m;
m=n;
n=c;
}
int main()
{
int a=1;int m=1;
int b=2;int n=2;
change1(&a,&b);
printf("-a-%d--\n",a);
printf("-b-%d--\n\n\n",b);
change2(&m,&n); //錯誤,錯誤,錯誤
printf("-m-%d--\n",m);
printf("-n-%d--\n\n\n",n);
return 0;
}
哎,chang2裡面的形參不是需要兩個位址嗎? &m,&n,不是取位址嗎?對啊!我傳入兩個位址,沒毛病啊!這是當初學C語言心中的疑惑,但是我是個廢柴!哦,書上說不用寫&,直接寫m,n就行了。好了我記住了!but!but!but!廢柴是不知道原理是什麼的,隻知道這樣子去用。好了,今天遇到問題報錯了吧!廢柴開始緊張了!
在這裡不得不吐槽教科書,垃圾,就寫一句“注意int &不是取位址,是引用,詳情自主百度”不就交代的很清楚了嗎?害我這個廢柴找了半天答案。垃圾教科書。
這裡引用“落辰衰”大佬的解釋:
1、int;
int是C++關鍵字,表示整型,其大小是32位有符号整型,表示的範圍是-2,147,483,648 到
2,147,483,647;在聲明和定義變量時使用,它表示的意思是所聲明或所定義的變量為整型變量。
如果其用于函數參數時,其傳遞方向為值傳遞,即隻能将實參的值傳遞給形參,而不能将
形參的值傳遞給實參。
例如:通過這種方式去進行交換兩個數是無法達到目的的。
例子1:
#include<iostream>
using namespace std;
voidswap1(inta,intb)
{
inttmp;
tmp = a;
a = b;
b = tmp;
}
int main(){
inta = 1;
intb = 2;
swap1(a, b);
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
system("pause");
return0;
}
結果為:a=1
b=2
因為傳遞的方式為值傳遞(單向傳遞);
2、int&;
這裡的&不是取位址符号,而是引用符号,引用是C++對C的一個重要補充。變量的引用就是
變量的别名,講的通俗一點就是另外一個名字,比如:“張三這個人在家裡,老爸老媽叫他
三娃子,那麼這個三娃子就是指張三這個人,如果叫張三去做某事,就是叫三娃子去做某事,
這兩個名字指的是同一個人。”同樣可以了解如果變量b是變量a的引用 那麼無論a,b中任
何一個值改變,另外一個也相應的改變,在聲明一個引用時,必須同時使之初始化,即聲
明它代表哪一個變量。請注意:由于引用不是獨立的變量,編譯系統不給它單獨配置設定存
儲單元,是以在建立引用時隻有聲明沒有定義,隻是聲明它與原有的某一變量的關系。
在聲明一個變量的引用後,在本函數執行期間,該引用一直與其代表的變量相聯系,不能
再作為其他變量的别名。說得簡單點:張三和三娃子是指同一個人,不能李四也叫三娃子,
如果可以這樣,叫三娃子去做什麼,是叫李四呢還是張三呢,這就會亂套了。是以在C++中
一個引用變量隻能對應一個原始的變量,不能對應兩個或多個原始的變量;
下面簡單說明引用:
a)聲明引用時必須指定它代表的是哪一個變量,即對它初始化。
int &a=b;這樣是聲明a是變量b的引用
如果是int &a;這樣就是錯的,沒有指定a代表哪一個變量。
b)引用與其所代表的變量共享同一記憶體單元,系統并不為引用另外配置設定存儲單元;
這個應該好了解;就像前面所說的,張三和三娃子都是同一個人,三娃子隻是張三的别名。
是以,對于 int &a=b;這個例子來說,要輸出a和b 的位址,肯定是相同的。
c)怎樣區分&是引用還是取位址符呢?方法是:判斷&a這樣的形式前是否有類型符即
int &a=b;如果有類型符(int)則是引用,否則是取位址運算符。
d)對引用的初始化,可以是一個變量名,也可以是另一個引用。
換句話說:張三的别名可以是三娃子,三小子……及其他多個别名
而三娃子也可以有其他的别名,比如說:老三,小三等
用程式可以這樣:
int a=1; //這裡是定義一個整形變量
int &b=a;//聲明b是整型變量a的别名
int &c=b;//聲明c是整型引用變量b的别名
int &d=a;//聲明d是整型變量a的别名
e)引用初始化後不能再被重新聲明為另一變量的别名
即三娃子既然是指張三這個人,就不能讓其他人也叫三娃子
即一個别名隻能對應一個原始變量,但是一個原始變量可以有多個别名,而且别名也可以
由自己的别名。
C++中增加引用主要是作為函數參數,進行資料傳遞的功能;
我們知道如果用變量名作為實參,其傳遞方向是單向的,而用引用作為實參其傳遞方向
是雙向的;
也許你會問,在c語言中不是有指針嗎,用指針進行參數傳遞不也是雙向的嗎?其實其
本質上也是值傳遞,隻不過是将變量的位址傳給指針,通過指針擷取變量的值,這樣做
雖能得到結果,但通過指針運算符去通路有關變量,比較麻煩。
下面分析一下使用引用和使用指針變量作為函數形參的不同(以例子1中的swap函數為例):
1、如果使用引用,則不必在swap函數設立指針變量,指針變量要另外開辟記憶體單元,其
内容是位址。而引用不是一個獨立的變量,并不占用記憶體單元
2、在main函數中調用swap函數時實參不必再變量名前加&以表示位址,系統傳遞的是
實參的位址不是實參的值。
3、使用指針變量時,為了表示指針變量所指向的變量,必須使用指針運算符*,而使用
引用時,引用就代表該變量,不必使用指針運算符*;
4、用引用完成的工作,用指針也能完成。但引用比指針的使用直覺、友善,直截了當,
不必“兜圈子”,容易了解。有些過去隻能用指針來處理的問題,現在可以用引用來代替,
進而降低了程式設計的難度。
對引用進一步說明:
1、不能建立void類型的引用。
因為任何實際存在的變量都是屬于非void類型的,void的含義是無類型或空類型,
void隻是在文法上相當于一個類型而已。
2、不能建立引用的數組。
如:char c[6]="hello";
char &rc=c;//錯誤
因為數組名是數組首元素的位址,本身不是一個占有存儲空間的變量。
3、可以将變量的引用的位址賦給一個指針,此時指針指向的是原來的變量。
這句話可以這樣說:将引用變量的位址賦給一個指針,此時指針指向的是引用變量,
相當于指向原來的變量
int a=2;
int &b=a;//這個聲明語句中的&是一個引用
int *p=&b;//這個指針初始化語句中的&是取位址運算符
上面一行等價于 int *p=&a;
但是不能定義指向引用類型的指針變量,不能寫成
int & *p=&a;//企圖定義指向引用類型的指針變量p,錯誤
因為引用不是一種獨立的資料類型,是以不能建立指向引用類型的指針變量。
4、可以建立指針變量的引用如
int i=5;
int *p=&i;
int * &pt=p;//建立指針變量p的引用pt
引用變量pt代表一個int *類型的資料對象(即指針變量)
5、可以用const對引用加以限定,不允許直接改變該引用的值,但是可以改變原
變量的值去改變引用的值;
int i=5;
const int &a=i;
a=3;//錯誤,因為引用a是const int 類型不能直接改變引用的值
但是可以這樣修改:
i=3;
此時輸出i和a都是3
6、可以用常量或表達式對引用進行初始化,但此時必須用const作聲明。
int i=5;
const int &a=i+1;
此時編譯系統是這樣處理的:生成一個臨時變量,用來存放該表達式的值,引用是
該臨時變量的别名、系統将“const int &a=i+1;”轉換為
int temp=i+1;
const int &a=temp;
臨時變量是在内部實作的,使用者不能通路臨時變量;
用這種辦法不僅可以用表達式對引用進行初始化,還可以用不同類型的變量對之
初始化;如
double d=3.1415926;
const int &a=d;
以上等價為:
double d=3.1415926;
int temp=d;
const int &a=temp;
如果在上面不用const則會發生錯誤
double d=3.1415926;
int &a=d;//未加const,錯誤
為什麼?因為如果可以這樣做,那麼修改引用a的值(如a=3.56),則臨時變量temp的值也
變為3.56,即修改了臨時變量temp的值,但不能修改變量d的值,這往往不是使用者所希望
的,即存在二義性。與其允許修改引用的值而不能實作使用者的目的,還不如不允許修改
引用的值。這就是C++規定對這類引用必須加const的原因。