C++ 的 const 是深層不可變,JS 的 const 只防重新賦值

JS 的 const 只防變數被重新賦值,防不住物件內部被改(要靠 Object.freeze())。 C++ 的 const 是「唯讀」,而且由編譯器在編譯期強制——初始化完成之後,任何嘗試修改它的程式碼都會直接噴錯。

// JavaScript
const arr = [1, 2, 3];
arr.push(4);       // ✅ 完全合法!const 只能防 arr = ...,防不了內容被改
// C++
const std::vector<int> arr = {1, 2, 3};
arr.push_back(4);  // ❌ 編譯錯誤!編譯器禁止呼叫任何可能修改 arr 的成員函式
arr[0] = 10;       // ❌ 編譯錯誤!裡面的值也是 const

把一個物件宣告為 const,它的直接成員全部跟著變成不可變。

const & 傳參:零拷貝加上唯讀保證

解題時最常見的參數寫法:

void process(const std::vector<int>& nums) {
    // nums[0] = 99;   // ❌ 編譯錯誤
}

兩個關鍵字各做一件事:

作用
&不複製整份容器——省記憶體、省時間, 傳遞
const保證唯讀,等於告訴呼叫者「這個函式不會動你的資料」

這是 C++ 裡同時拿到高效能與不可變保證的標準寫法。

一個重要的例外:const 穿不過指標

「宣告 const 就全面不可變」只對直接成員成立。const 不具傳遞性——它管得到指標本身,管不到指標指向的東西:

struct S { int* p; };
const S s;
 
// s.p = otherPtr;   // ❌ 指標本身不能改(它變成 int* const)
*s.p = 42;           // ✅ 合法!指向的內容照改

const 到底鎖住哪一半,取決於它寫在哪裡——見 指標的 const 位置決定是指標不可變還是內容不可變。

JS vs C++ 對照

特性JavaScriptC++
宣告語法const x = ...const int x = ...
物件/陣列內部成員預設仍可變(需 Object.freeze())宣告 const 即不可變(但穿不過指標)
檢查時機執行期編譯期直接報錯
編譯期常數無constexpr,見 constexpr 是編譯期常數,const 只是執行期唯讀
函式參數唯讀傳遞無原生防護const Type&(零拷貝且強制唯讀)

最後一列要講清楚 JS 那半邊:JS 是「把參照當成值傳」,不是 pass-by-reference——

function f(o) {
  o.x = 1;   // ✅ 影響呼叫端(改的是同一個物件)
  o = {};    // ❌ 不影響呼叫端(真正的引用傳遞會影響)
}

所以 JS 缺的不是「引用傳遞」,是沒有辦法在語言層面禁止被呼叫的函式去改你傳進去的物件。