函數是獨立的程式碼區塊,具備名稱、返回類型、參數列表。良好的函數設計能實現程式碼復用、模組化、易於測試。函數原型宣告(如 int func(double, int);)讓編譯器提前知道介面,分離介面與實作。
複製實參值給形參,函數內修改不影響原值。適合小型資料(int、double 等)。
int passByValue(int a, int b) {
a += 5; b += 5; // 只修改副本
return a + b;
}
傳遞變數位址,函數可透過指標修改原值。需檢查空指標。
int passByPointer(int* a) {
*a += 5; // 修改原值
return *a;
}
形參是實參別名,語法簡潔且效率高(無複製開銷)。大型物件首選 const T& 避免拷貝。
int passByRef(int& a, int& b) {
a += 5; b += 5;
return a + b;
}
鐵律:絕不返回區域變數位址。區域變數隨函數結束銷毀,返回的指標成懸空指標。
int* badReturn(int a, int b) {
int num = a + b; // 區域變數
return # // 錯誤:返回區域變數位址
}
int* goodReturn(int a, int b) {
int* p = new int(a + b + 10); // 堆上配置
return p; // 呼叫端必須 delete
}
警示:動態記憶體易造成記憶體洩漏,現代 C++ 應優先使用智慧指標(unique_ptr、shared_ptr)或容器。
static 區域變數只初始化一次,生命週期贯穿整個程式,但作用域仍限於函數內。適用於呼叫計數、快取等場景。
int callCounter(int a, int b) {
static int count = 0; // 僅首次呼叫初始化
++count;
cout << "第 " << count << " 次呼叫" << endl;
return a + b;
}
static 關鍵字多重含義總表| 位置 | 作用 |
|---|---|
| 函數內區域變數 | 靜態儲存期,跨呼叫保值 |
| 全域變數/函數 | 內部連結,僅本檔案可見 |
| 類別靜態成員 | 全類別共享單一實例 |
函數直接/間接呼叫自身。必須有基底情況終止遞歸,否則無限遞歸導致堆疊溢位。
int factorial(int n) {
if (n <= 1) return 1; // 基底情況
return n * factorial(n - 1);
}
#include <iostream>
using namespace std;
// 函數宣告
int passByValue(int, int);
int passByPointer(int*);
int passByRef(int&, int&);
int* returnPointer(int, int);
int staticCounter(int, int);
int factorial(int);
int main() {
int a = 5, b = 5;
int result;
// 1. 傳值
result = passByValue(a, b);
cout << "傳值後 a=" << a << " b=" << b << " result=" << result << endl;
// 2. 傳址
result = passByPointer(&a);
cout << "傳址後 a=" << a << " result=" << result << endl;
// 3. 傳參考
result = passByRef(a, b);
cout << "傳參考後 a=" << a << " b=" << b << " result=" << result << endl;
// 4. 返回指標
int* p = returnPointer(a, b);
cout << "返回指標值=" << *p << endl;
delete p; // 必須釋放
// 5. 靜態計數器
for (int i = 0; i < 4; ++i) staticCounter(a, b);
// 6. 遞歸階乘
cout << "5! = " << factorial(5) << endl;
return 0;
}
// 實作略(見上文各段落)
const&、需修改傳 &、可選參數用指標。std::optional。static:善用靜態區域變數保持狀態,但注意執行緒安全。