java的值傳遞理解:
代碼1:
public class Test { /** * @param args */ public static void main(String[] args) { StringBuffer buffer= new StringBuffer("colin"); SChange(buffer); System.out.println( buffer); } public static void SChange (StringBuffer str) { str= new StringBuffer("huang"); } }代碼2:
public class Test { /** * @param args */ public static void main(String[] args) { StringBuffer buffer= new StringBuffer("colin"); SChange(buffer); System.out.println( buffer); } public static void SChange (StringBuffer str) { //str= new StringBuffer("huang"); str.append(" huang"); } }再分別用兩張圖來解釋上面的碼1、代碼2:
原始狀態
代碼1圖解:
代碼2理解:
程式碼一中, copy的那個引用, 指向了一個新的物件。 但原對象還是沒有變化的。
程式碼二中, copy的那個引用, 把原物件改變了。
這就是Java的值傳遞。
C++中兩種傳遞的差別:
對於C++值傳遞、引用傳遞、指標方式用以下程式碼理解,自己執行測試
#include <stdio.h> #include <iostream> #include <typeinfo> void ByValue(int a) { a = a + 1; } void ByRef(int& a) { a = a + 1; } void ByPointer(int* a) { *a = *a + 1; } int main(int argv, char** args) { int v = 1; ByValue(v); ByRef(v); // Pass by Reference ByPointer(&v); // Pass by Value int* vp = &v; ByPointer(vp); std::cout << v << std::endl; // std:: cout << typeid(vp).name() << std::endl; // std::cout << typeid(&vp).name() << std::endl; std::cout << "end" << std::endl; }第一個是值傳遞,第二個函數是引用傳遞,但是後面兩種,同一個函數,一次呼叫是Call by reference, 一次是Call by value。
因為:
ByPointer(vp); 沒有改變vp,其實是無法改變。值傳遞
ByPointer(&v); 改變了v。引用傳遞(你可能會說,這傳遞的其實是v的地址,而ByPointer無法改變v的地址,所以這是Call by value。這聽起來可以自圓其說,但是v的地址,是個純數據,在調用的方程式碼中並不存在,對於呼叫者而言,只有v,而v的確被ByPointer函數改了,這個結果,正是Call by reference的行為。
nob:以上理解認可,補充指標方式可以使用兩種方式,值傳遞:傳遞一個指標;引用傳遞:傳遞一個變數的位址或引用;如果使用typeid(x).name()檢視&v和vp發現都是Point類型,所以兩種表現,同一種結果。你可能會想我這樣
ByValue(&v); //error
,而在C++中傳遞不同類型的參數直接編譯不通過。
總結:
所以我覺得傳值還傳引用先看記憶體上怎麼走就行了
share記憶體就是傳引用,copy記憶體就是傳值(先拋開一些特殊情況)
這樣的話:
C/C++:預設傳值,引用傳引用,指標單獨理解(指標可以理解為既可以傳值、也可以傳引用,而產生結果相同)
JAVA:基礎資料型別值傳遞,物件也是值傳遞(把這個物件的引用copy了一份)
C#:值型別傳值,引用型別傳引用,ref/out特殊理解
JAVA和C#的string要特殊理解,表像是傳值,實際上要看虛擬機器實現