Java,C#已經比較熟悉,最近在從0開始自學C++。學習過程中必然會與Java,C#進行對比,有吐槽,也有點贊。 先來講講最基本也是最重要的部分:參數傳遞的方式。 對於類型, Java分基本類型、複合類型,從另外一個角度分是值類型,引用類型。在展開對比前, 我們先來看看三個關鍵方式: 值 創建新的 ...
Java,C#已經比較熟悉,最近在從0開始自學C++。學習過程中必然會與Java,C#進行對比,有吐槽,也有點贊。
先來講講最基本也是最重要的部分:參數傳遞的方式。
對於類型, Java分基本類型、複合類型,從另外一個角度分是值類型,引用類型。在展開對比前, 我們先來看看三個關鍵方式:
-
值
- 創建新的副本,與原來的沒有關係
-
地址(指針)
- 把對象所在記憶體的地址傳遞過去
-
引用
- 可以理解為變數的別名
舉個例子:
1 void testMethodA(int input) { 2 input = 999; 3 } 4 5 void testMethodB(int* input) { 6 //int newValue = 888; 7 *input = 888; 8 } 9 10 void testMethodC(int& input) { 11 input = 777; 12 } 13 14 int main() { 15 16 int input = 111; 17 cout << "Original: " << input << endl; 18 testMethodA(input); 19 cout << "After testMethodA: " << input << endl; 20 cout << input; 21 testMethodB(&input); 22 cout << "After testMethodB: " << input << endl; 23 cout << input; 24 testMethodC(input); 25 cout << "After testMethodC: " << input << endl; 26 27 std::cin.get(); 28 29 // What is the value of input? 30 31 }
運行後的結果:
Original: 111 After testMethodA: 111 111After testMethodB: 888 888After testMethodC: 777
解釋一下:
函數 testMethodA 的參數是值傳遞的,調用函數後,創建了一個input的副本,副本的值改變了, 但是input值沒有被改變。
函數 testMethodB 的參數是地址(指針)傳遞的,函數內修改了input指向的那塊記憶體區域,所以input的值也被改變了。
函數 testMethodC的行為看起來是和函數 testMethodB是一樣的, input值也被改變了,他們有什麼區別呢?
區別在於:
傳遞地址,函數內改變的是變數指向的那塊記憶體區域的內容。
傳遞引用,函數內改變的是變數的指向,換句話說,input指向的記憶體地址都變了。
如下圖:
在C++裡面,所有的類型,不管是基礎數據類型,結構體,還是類,預設都是“值”傳遞的;顯式聲明為指針,才是傳地址;顯式聲明為引用,可以認為就是給變數起了一個別名。
在Java裡面,只有基礎數據類型(int, double, float等),是值傳遞的,所有的類對象,都是傳地址(註意,不是傳引用), 實際上,java裡面沒有引用傳遞的概念。
在C#裡面, 基礎數據類型,結構體, 預設都是值傳遞;所有的對象, 預設都是傳地址;如果想傳引用,在參數前面加ref關鍵字,例如:
1 void testMethodC(ref int input) { 2 input = 777; 3 }