再談“引用”

來源:互聯網
上載者:User

  晚上又把Netbeans6.1給裝上了,不過不是用來做java的,是做C++的,唉,無奈啊,誰叫上學期給掛了呢。想想自己其實也挺酷,一張C++的卷子,全用C#來解答,在答到中間程式題時,不知咋的,叛逆心突然膨脹,覺得在紙張上寫程式很無聊,就寫了幾個“同上”,“… ...”,結果就……,不過老師其實還不錯,後來問他時,他說最後一題給了我滿分(只有這題有寫完整),這說明他還是沒有過分計較語言的。

 

   話說回來,其實C++也不是那麼可惡,雖然C#比它elegant了許多。複習起C++,還是比較容易接受的,不過有些地方不說還真是不注意,正好看到了C++中的引用,就隨便拉出word扯兩句。

 

   在C#中,引用是指記憶體的地址,比如建立一個對象Person p = new Person();,那麼p所儲存的,就是Person執行個體(在託管堆上分配記憶體)的地址,而p本身,是棧上的一個變數。

 

   那在C語言中呢,有指標的概念,在C++中又有引用的概念,感覺C++中的引用和C#中的引用還算是基本一樣的意思,但在C++的書中往往解釋很多,因為指標的存在。那指標變數和引用的區別在哪呢。

 

  首先,指標不是指標變數,指標是記憶體位址,而指標變數,是一個儲存著這個地址的變數,就像前面C#中的Person p = new Person(),這個p其實就可以稱為一個指標變數,它首先是一個變數,然後它儲存的值是一個記憶體位址(當然,C#中不會這麼稱呼它的)。

 

   而C++中的引用,其實是變數的“別名”,比如:int a = 10; 那麼,a是在棧上開闢的一塊記憶體空間,儲存著10,而a的引用(別名)所儲存的內容,也就是a所在的記憶體空間的上整型值10,可以把引用用“別名”來代替,再用“別名”的字面意思來理解,其實就比較好理解了。a的別名,則可認為除了名字和a不一樣外,其它完全一樣,地址,儲存內容,都一樣。

 

a的別名(引用)是這樣定義的:

   

int a = 10; 
int &b = a; //定義a的引用b

 

從函數傳參可以更深刻的理解它,看: 

 

1void Swap(int a , int b);
2//…
3int c = 10;
4int d = 12;
5Swap(c, d);

 

當調用Swap (c, d)時,有一個copy的過程,在Swap函數體中的a和b,僅僅只是變數c和d的副本,它們儲存的內容相同,但所在的記憶體空間並不一樣。

 

  再看:

1void Swap (int *a, int *b);
2//
3int c = 10;
4int d = 12;
5Swap(&c, &d);
6

 

  當調用Swap (&c, &d)時,一樣,還是有一個copy的過程,但和上面的又不一樣,上面copy的是變數,這裡copy的是指標變數(儲存記憶體位址),也就是說,在調用時,它會建立兩個指標變數,然後把c和d的地址分別賦給它們,而在Swap函數體中執行時,就可以對這兩個指標變數進行操作,也就是說,我們可以從這兩個指標變數得到實參的地址,那麼,改變實參的值當然沒有問題。但是有一點是需要注意的,這裡“建立了兩個指標變數”。 

 

  再看:

1Swap (int &a, int &b);
2//
3int c = 10;
4int d = 12;
5Swap(c, d);

 

  這裡用上了別名,Swap函數接受兩個參數,它們是變數的引用(別名),當調用Swap (c, d)時,就不再有copy的過程了,在Swap函數體中,直接操縱著c和d,因為傳遞的是它們的別名,這就好比水言木是我的網名(別名),別人摔了水言木一巴掌,那就是實實在在地摔了我一巴掌。

 

  說到這裡,就轉過來看看C#中的ref關鍵字吧,看:

 

1int Swap(ref int a, ref int b) { … }
2//
3int c = 10;
4int d = 12;
5Swap(ref c, ref d);
6

 

  其實ref的作用和上面C++中的引用(別名)是一樣的,當用上了ref時,就不再有傳參時的參數拷貝過程了,而如果沒用ref,那在Swap函數體中的a和b,其實就是c和d的副本。

 

  而C#中,是沒有指標這東東的,那它有沒有類似C++中傳遞指標的情況呢?有。看下面:

 

1Swap(Person p) { … }     //為了少打點字,這裡就不考慮Swap函數的語義了
2//
3Person person = new Person();
4Swap(person);

 

  person是類的執行個體名(對象名),它所儲存的,就是執行個體在託管堆中的地址,如上面所說,我們可以認為它是C++中的指標變數,那麼,當調用Swap (person)時,就有一個copy的過程:在棧上開闢一塊空間,儲存person的值(值是Person執行個體的地址),然後在Swap函數體中操作的p,其實是棧上的另一塊空間,因為它和實參person所儲存的內容一樣,都是執行個體的地址,所以,在函數中對p屬性的賦值可以改變實參person相應的屬性值,但是,如果在Swap中有一句p = new Person(),那麼,之後的p,則是指向了另一塊堆上的空間(新Person執行個體的地址)。

 

   而如果用的是ref:

 

1Swap(ref Person p) {…}
2//
3Person person = new Person();
4Swap(ref person);
5

 

那麼,傳參時就沒有了參數copy的過程,於是,若在Swap中進行p = new Person(),那也是會使實參的值(地址)改變,那原先的Person執行個體,就會成為一個等待GC來收集的垃圾了。

 

洋洋洒洒寫了不少字,到此結束。

 

相關文章:小記一次讓我誤會的引用傳參

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.