S SmartDocs
系列: C++ cpp 169 行 · 更新于 2026-04-03

references.cpp

C++/Part1_基礎入門/Ch06_指標與參考/references.cpp

// ============================================================
// Ch06 — 參考(References)
// 編譯:g++ -std=c++17 -Wall -o references references.cpp
// ============================================================

#include <iostream>
#include <string>
#include <vector>

// ── 函式原型 ──
void swapByRef(int& a, int& b);
void printConst(const std::string& s);
int& getElement(std::vector<int>& vec, size_t index);
void modifyByRef(int& val);
void readByConstRef(const int& val);

// ── 主程式 ────────────────────────────────────────
int main() {
    std::cout << "===== Ch06:參考 =====\n\n";

    // ── 1. 基本宣告與別名行為 ──
    std::cout << "【1】基本宣告與別名行為\n";

    int x = 42;
    int& ref = x;  // ref 是 x 的別名

    std::cout << "x   = " << x << "\n";
    std::cout << "ref = " << ref << "\n";
    std::cout << "&x  = " << &x << "\n";
    std::cout << "&ref= " << &ref << "(與 &x 相同)\n\n";

    // 透過參考修改
    ref = 100;
    std::cout << "執行 ref = 100 後:\n";
    std::cout << "x   = " << x << "(x 也變了)\n";
    std::cout << "ref = " << ref << "\n\n";

    // 透過原始變數修改
    x = 200;
    std::cout << "執行 x = 200 後:\n";
    std::cout << "x   = " << x << "\n";
    std::cout << "ref = " << ref << "(ref 也變了)\n\n";

    // ── 2. 參考必須初始化 ──
    std::cout << "【2】參考必須初始化\n";
    std::cout << "int& ref;       ← 編譯錯誤!\n";
    std::cout << "int& ref = x;   ← 正確\n\n";

    // ── 3. 參考不能重新綁定 ──
    std::cout << "【3】參考不能重新綁定\n";

    int a = 10, b = 20;
    int& refA = a;

    std::cout << "refA 綁定到 a,refA = " << refA << "\n";

    refA = b;  // 這不是重新綁定!而是把 b 的值賦給 a
    std::cout << "執行 refA = b 後:\n";
    std::cout << "a    = " << a << "(a 被修改為 b 的值)\n";
    std::cout << "refA = " << refA << "\n";
    std::cout << "b    = " << b << "(b 不受影響)\n\n";

    // ── 4. 參考作為函式參數 ──
    std::cout << "【4】參考作為函式參數\n";

    int m = 100, n = 200;
    std::cout << "交換前:m = " << m << ", n = " << n << "\n";
    swapByRef(m, n);
    std::cout << "交換後:m = " << m << ", n = " << n << "\n\n";

    // 修改參數
    int val = 5;
    std::cout << "修改前:val = " << val << "\n";
    modifyByRef(val);
    std::cout << "修改後:val = " << val << "\n\n";

    // ── 5. const 參考 ──
    std::cout << "【5】const 參考\n";

    int num = 42;
    const int& cref = num;
    std::cout << "const int& cref = num → cref = " << cref << "\n";
    std::cout << "cref = 99;  ← 編譯錯誤!不能透過 const 參考修改\n\n";

    // const 參考可以綁定到暫時值(rvalue)
    const int& tempRef = 999;
    std::cout << "const int& tempRef = 999 → tempRef = " << tempRef << "\n";
    std::cout << "(一般參考 int& r = 999; 會編譯錯誤)\n\n";

    // const 參考用於函式參數
    std::string greeting = "Hello, C++!";
    std::cout << "const 參考作為函式參數:\n";
    printConst(greeting);
    printConst("暫時字串也可以傳入");
    std::cout << "\n";

    // ── 6. 從函式回傳參考 ──
    std::cout << "【6】從函式回傳參考\n";

    std::vector<int> vec = {10, 20, 30, 40, 50};
    std::cout << "原始 vec[2] = " << vec[2] << "\n";

    getElement(vec, 2) = 999;  // 透過回傳的參考直接修改
    std::cout << "getElement(vec, 2) = 999 後:vec[2] = " << vec[2] << "\n\n";

    // ── 7. 參考 vs 指標比較 ──
    std::cout << "【7】參考 vs 指標比較\n";

    int value = 42;
    int& refVal  = value;     // 參考
    int* ptrVal  = &value;    // 指標

    std::cout << "┌──────────────┬──────────────────┬──────────────────┐\n";
    std::cout << "│     特性      │   參考(int&)     │   指標(int*)    │\n";
    std::cout << "├──────────────┼──────────────────┼──────────────────┤\n";
    std::cout << "│ 宣告語法     │ int& r = x;       │ int* p = &x;     │\n";
    std::cout << "│ 存取值       │ r(直接使用)       │ *p(需解參考)    │\n";
    std::cout << "│ 可為空       │ 不可              │ 可(nullptr)     │\n";
    std::cout << "│ 可重新綁定   │ 不可              │ 可               │\n";
    std::cout << "│ 需要初始化   │ 必須              │ 不一定            │\n";
    std::cout << "│ 函式呼叫語法  │ f(x)             │ f(&x)            │\n";
    std::cout << "└──────────────┴──────────────────┴──────────────────┘\n\n";

    // 語法差異示範
    std::cout << "語法差異示範:\n";
    std::cout << "  參考:refVal = " << refVal << "(直接使用)\n";
    std::cout << "  指標:*ptrVal = " << *ptrVal << "(需要 * 解參考)\n\n";

    // ── 8. 使用建議 ──
    std::cout << "【8】使用建議\n";
    std::cout << "✔ 使用參考:\n";
    std::cout << "  - 函式參數傳遞(避免複製大物件)\n";
    std::cout << "  - 運算子多載\n";
    std::cout << "  - 確定不會為空的情況\n";
    std::cout << "  - 範圍 for 迴圈中修改元素:for (auto& elem : container)\n\n";

    std::cout << "✔ 使用指標:\n";
    std::cout << "  - 可能為空(可選參數)\n";
    std::cout << "  - 需要重新指向不同物件\n";
    std::cout << "  - 動態記憶體管理(new/delete 或智慧指標)\n";
    std::cout << "  - 與 C 程式碼或 API 互動\n";

    return 0;
}

// ── 函式定義 ──────────────────────────────────────

void swapByRef(int& a, int& b) {
    int temp = a;
    a = b;
    b = temp;
}

void printConst(const std::string& s) {
    std::cout << "  \"" << s << "\"(長度 = " << s.size() << ")\n";
}

// 回傳參考:讓呼叫者可以直接修改容器中的元素
int& getElement(std::vector<int>& vec, size_t index) {
    return vec.at(index);
}

void modifyByRef(int& val) {
    val *= 10;
}

void readByConstRef(const int& val) {
    std::cout << "值 = " << val << "\n";
}

相关文章