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

各程式語言中的指標與參考:C/C++、Java、C# 深度對比

     編輯:關於C語言

前言

近期專案中發現團隊成員對 C/C++ 指標與參考的區別模糊不清。隨著 Java、C# 等高階語言普及,開發者與作業系統底層的距離拉大,導致指標這一 C/C++ 核心機制被邊緣化甚至遺忘。本文系統梳理三種參數傳遞機制,並跨語言對比其設計哲學。

一、 C/C++ 三種參數傳遞機制實戰對比

場景:查找使用者函式

// 主程式
CString strUserId = "001";
CString strUserName = "無名";
BOOL bFind = FindUserName(strUserId, strUserName);

1. 傳參考 CString&(推薦用於輸出參數)

BOOL FindUserName(CString& strUserIdParam, CString& strUserNameParam) {
    if (strUserIdParam == "001") {
        strUserNameParam = "王澤賓";  // 修改實參物件
        return TRUE;
    }
    return FALSE;
}
// 結果:彈出 "User Name:王澤賓"
  • strUserNameParam 是 strUserName 的別名,類似 Windows 捷徑或 Linux 符號連結
  • 無額外物件建構/複製開銷
  • 語法簡潔,如同傳值般自然

2. 傳值 CString(預設行為)

BOOL FindUserName(CString strUserIdParam, CString strUserNameParam) {
    if (strUserIdParam == "001") {
        strUserNameParam = "王澤賓";  // 修改副本
        return TRUE;
    }
    return FALSE;
}
// 結果:彈出 "User Name:無名"(原物件未變)
  • 呼叫時觸發複製建構函式,產生獨立副本
  • 函式內修改不影響實參
  • 大型物件傳值效能損耗顯著

3. 傳址 CString*(C 風格,輸出參數替代方案)

BOOL FindUserName(CString* pstrUserIdParam, CString* pstrUserNameParam) {
    if (*pstrUserIdParam == "001") {
        *pstrUserNameParam = "王澤賓";
        return TRUE;
    }
    return FALSE;
}
// 呼叫:FindUserName(&strUserId, &strUserName);
// 結果:彈出 "User Name:王澤賓"
  • 傳遞指標副本,兩指標指向同一記憶體
  • 需手動解參考 *,語法較繁瑣
  • 可傳遞 nullptr 表示「無輸出」

二、 指標 vs 參考:核心差異表

特性指標參考
可為 null是否(宣告必須初始化)
可重新繫結隨時修改指向初始化後不可變更
語法操作*p, p->直接使用變數名
編譯期實體獨立變數(佔記憶體)別名(編譯後等同指標)
安全性野指標、懸空指標風險語法層面消除空參考風險

關鍵程式碼證明:參考不可重繫結

int i = 5, j = 6;
int& k = i;  // k 繫結 i
k = j;       // 僅賦值,k 仍繫結 i,i 變為 6
// k 無法變成 j 的參考

三、 參考的本質與價值

「參考實際上只是編程語言中語法層面的概念,經編譯後實際執行的代碼中與指標沒有任何區別。」

引入參考帶來雙重紅利:

  1. 程式碼簡潔:呼叫端無 &,被呼叫端無 *
  2. 部分消除指標不安全:強制初始化、不可為 null、不可重繫結

四、 Java / C# 的設計選擇:拋棄指標,擁抱參考語意

統一規則

  • 基本型別(int、bool 等)→ 傳值
  • 物件型別(class 實例)→ 傳參考(實為傳遞參考的副本)

Java 範例驗證

class ObjUser { String strName = "init value"; }
public class Test {
    ObjUser user = new ObjUser();
    int age = 60;
    void changeObj(ObjUser u) { u.strName = "changed value"; }
    void changeInt(int a) { a = 80; }
    public static void main(String[] args) {
        Test t = new Test();
        System.out.println("Before changeObj: " + t.user.strName); // init value
        t.changeObj(t.user);
        System.out.println("After changeObj: " + t.user.strName);  // changed value
        System.out.println("Before changeInt: " + t.age);          // 60
        t.changeInt(t.age);
        System.out.println("After changeInt: " + t.age);           // 60
    }
}

結果證明:物件傳參考(可修改內部狀態),基本型別傳值(不可修改)。

若需物件傳值

Java 使用 clone() 深層複製後再傳遞;C# 結構體(struct)屬值型別,預設傳值;PHP 保留 & 明確指定傳參考。

五、 總結與建議

  • C/C++ 開發者:務必精通指標與參考,理解編譯模型,善用參考簡化介面、用指標表達可選/所有權語意
  • Java/C# 開發者:理解「傳遞參考的副本」本質,避免誤以為物件不可變
  • 跨語言協作:介面設計時明確語意——輸入參數用 const T&,輸出參數用 T& 或 T*,所有權轉移用智慧指標

本文出自 “網站架構之家” 博客,請務必保留此出處 https://wangzebin.blog.51cto.com/653300/182452

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved