首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 與 C++ 參數傳遞機制深度對比:傳值、傳引用、指標語意

     編輯:Java 相關知識

參數傳遞機制核心差異:Java vs C++

「Java 是傳值還是傳引用?」這是經典面試題,也是無數開發者的困惑來源。本文從記憶體模型、語言語意、編譯器行為三個維度,深度對比 Java、C++、C# 三大語言的參數傳遞機制,徹底釐清傳值、傳引用、指標傳遞的本質區別。

核心結論先行

語言基本型別物件/類別型別備註
Java傳值 (複製值)傳值 (複製引用/指標)無傳引用機制,引用本身不可修改
C++傳值 (預設)傳值 (預設,複製物件)支援真正傳引用 (T&) 與指標傳遞 (T*)
C#傳值 (結構體)傳引用 (類別)ref/out 強制傳引用

Java:只有傳值

基本型別:複製位元模式


void primitive(int x) { x = 10; }
int a = 5;
primitive(a); // a 仍為 5,x 是 a 的位元複製

引用型別:複製引用 (指標值)


class Box { int value; }

void modifyRef(Box b) {
    b.value = 20;        // ✅ 修改物件內部狀態:透過複製的引用找到同一物件
    b = new Box();       // ❌ 修改區域引用:b 指向新物件,外部原引用不變
    b.value = 30;        // 只影響新物件
}

Box original = new Box();
original.value = 5;
modifyRef(original);
System.out.println(original.value); // 20 (內部狀態被修改)

記憶體圖解

呼叫前:                    呼叫 modifyRef 時:
main 棧框                  modifyRef 棧框
┌─────────┐                ┌─────────┐
│ original│ ─────────────► │    b    │  (複製引用值,指向同一物件)
└─────────┘                └─────────┘
      │                           │
      ▼                           ▼
┌─────────────────────────────────────────┐
│              Heap                       │
│  ┌──────────────┐                       │
│  │ Box@0x1234   │ ◄─────────────────────┘
│  │ value = 5    │
│  └──────────────┘
└─────────────────────────────────────────┘

C++:三種傳遞語意


#include 

void byValue(int x) { x = x + 1; }
void byRef(int& x) { x = x + 1; }       // 真正傳引用:別名
void byPointer(int* x) { *x = *x + 1; } // 指標傳遞:傳遞位址

int main() {
    int v = 1;
    byValue(v);    // v = 1 (複製值)
    byRef(v);      // v = 2 (別名修改)
    byPointer(&v); // v = 3 (解引用修改)
    
    int* vp = &v;
    byPointer(vp); // v = 4 (傳遞指標副本,但解引用修改同一記憶體)
    std::cout << v; // 4
}

關鍵差異

  • byRef(int& x):x 是 v 的別名,編譯器層面綁定,修改 x 即修改 v
  • byPointer(int* x):x 是指標副本 (傳值),但 *x 解引用修改 v
  • C++ 允許同一函數以不同方式呼叫:byPointer(&v) (傳址/引用語意) vs byPointer(vp) (傳指標值)

C#:值類型 vs 參考類型


struct Point { public int X, Y; } // 值類型
class Node { public int Value; }  // 參考類型

void val(Point p) { p.X = 10; }           // 複製結構體
void refVal(ref Point p) { p.X = 10; }    // 傳引用 (ref)
void cls(Node n) { n.Value = 10; }        // 複製引用 (同 Java)
void refCls(ref Node n) { n = new Node(); } // 傳引用可修改引用本身

String 特殊性:Java vs C#

語言String 類型傳遞行為不可變性
Java類別 (參考型別)傳值 (複製引用)不可變,修改產生新物件
C#類別 (參考型別)傳引用 (複製引用)不可變,修改產生新物件

兩者行為一致:void f(String s) { s = "new"; } 不影響外部原字串,因為 s 是複製的引用,重新指向新物件。

統一理解框架:記憶體視角

判斷傳值還是傳引用,看記憶體發生什麼:
• 複製記憶體內容 → 傳值 (含複製指標/引用)
• 共享記憶體位址 → 傳引用 (別名綁定)
• 指標:可視為「可傳值、可傳引用」的雙重身分,但解引用行為為傳引用語意

實務影響總結

  1. Java:方法無法修改呼叫端的區域變數引用,只能修改物件內部狀態。需修改引用請回傳新物件或用包裝類/陣列/AtomicReference
  2. C++:T& 避免大物件拷貝、T* 可選參數/輸出參數、const T& 唯讀避免拷貝
  3. C#:ref/out 明確表達修改引用意圖,結構體預設傳值需注意效能
  4. 通用原則:傾向不可變物件、函數式風格、輸出參數用回傳值/Result 物件替代
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved