05引用和指標,引用傳遞和指標傳遞
指標:
引用:
區別:
1.首先,引用不可以為空,但指標可以為空。!故定義一個引用的時候,必須初始化。因此如果你有一個變數是用於指向另一個物件,但是它可能為空,這時你應該使用指標;如果變數總是指向一個物件,i.e.,你的設計不允許變數為空,這時你應該使用引用。
2.引用不可以改變指向,對一個物件"至死不渝";但是指標可以改變指向,而指向其它物件。說明:雖然引用不可以改變指向,但是可以改變初始化物件的內容。例如就++操作而言,對引用的操作直接反應到所指向的物件,而不是改變指向;而對指標的操作,會使指標指向下一個物件,而不是改變所指物件的內容。
3.再次,引用的大小是所指向的變數的大小,因為引用只是一個別名而已;指標是指標本身的大小,4個位元組。
4.引用比指標更安全。由於不存在空引用,並且引用一旦被初始化為指向一個物件,它就不能被改變為另一個物件的引用,因此引用很安全。對於指標來說,它可以隨時指向別的物件,並且可以不被初始化,或為NULL,所以不安全。
5.指標指向一塊記憶體,它的內容是所指記憶體的地址;而引用則是某塊記憶體的別名,引用不改變指向。
引用傳遞和指標傳遞:
- 指標傳遞引數本質上是值傳遞的方式,它所傳遞的是一個地址值。值傳遞過程中,被調函式的形式引數作為被調函式的區域性變數處理,即在棧中開闢了記憶體空間以存放由主調函式放進來的實參的值,從而成為了實參的一個副本。值傳遞的特點是被調函式對形式引數的任何操作都是作為區域性變數進行,不會影響主調函式的實參變數的值。
- 引用傳遞過程中,被調函式的形式引數也作為區域性變數在棧中開闢了記憶體空間,但是這時存放的是由主調函式放進來的實參變數的地址。被調函式對形參的任何操作都被處理成間接定址,即通過棧中存放的地址訪問主調函式中的實參變數。正因為如此,被調函式對形參做的任何操作都影響了主調函式中的實參變數。
引用傳遞和指標傳遞是不同的,雖然它們都是在被調函式棧空間上的一個區域性變數,但是任何對於引用引數的處理都會通過一個間接定址的方式操作到主調函式中的相關變數。而對於指標傳遞的引數,如果改變被調函式中的指標地址,它將影響不到主調函式的相關變數。如果想通過指標引數傳遞來改變主調函式中的相關變數,那就得使用指向指標的指標,或者指標引用(對這句話,不是太理解)。
ps:個人理解:採用地址傳遞的方式,要想改變主函式的實引數據,那麼就得操作指標(地址)指向的資料,而不能直接操作地址的具體數值(這是沒有影響的)。
#include<iostream> #include<stdlib.h> using namespace std; void swap_int(int* a, int* b) { /*int* temp = a; a = b; b = temp;*/========無變化============直接操作的指標a,b。因為a,b是地址,還是屬於值傳遞,從主函式中備份過來了,也就是說這裡我們是把指標備份了。備份的內容還是值傳遞。而備份的內容指向的東西是在主函式空間裡的,所以就可以改變實參的值。 *a = 11; *b = 22;//==========變化==========操作的*a,*b。就是備份的內容指向的東西。 } void test(int* p) { int a = 1; p = &a; cout << p << " " << *p << endl << endl;; } int main(void) { int a = 1, b = 2; int* p = NULL; cout << a << " " << &a << " " << b << " " << &b << endl << endl; swap_int(&a, &b); cout << a << " " << &a << " " << b << " " << &b << endl << endl; test(p); if (p == NULL) cout << "指標p為NULL" << endl << endl; system("pause"); }
關於指標和引用的區別在於:
指標是對地址的一份拷貝,雖然對其的使用,可以通過地址來改變實參的值,
但如果對這個指標的拷貝,做出改變,那麼這種改變將不影響實參。
而引用,是一種間接的操作,對形參的所有改變,都會通過間接的操作,對映到實參中,引用本身就是一種別名,所以對這個別名的操作,就是對實參的操作。