# 函式 ## 自訂函式 每個函式有返回型別、名稱、參數列表及主體。`void` 函式表示無返回值,`int`、`double` 等表示返回具體資料型別 ```cpp #include <iostream> using namespace std; // 定義無返回值的函式 void greet() { cout << "Hello from function!" << endl; } // 定義有返回值的函式 int add(int a, int b) { return a + b; } int main() { greet(); // 呼叫 greet 函式 int result = add(5, 10); // 呼叫 add 函式 cout << "5 + 10 = " << result << endl; return 0; } ``` :::danger 函式名稱不得用數字開頭 ::: :::spoiler 專案多載 如果你的project中有多個檔案,每個檔案中都有 “ABC” 這個function 。這時會導致編譯錯誤 **多重定义:multiple definition of** 解決辦法就是在每個function 前 加上靜態的 static 公有與私有的詳細解說在下文 [@Program](https://www.notion.so/16d9def5443d80658f3fed2b96357a3a?pvs=21) ::: ## 先宣告 ```cpp= #include <iostream> using namespace std; int main() { int x, y; // ↓↓↓↓ 先宣稱「有這樣子的函數存在」但略過本體 ↓↓↓↓ int f(int); cin >> x; y = f(x); cout << y << '\n'; return 0; } // 宣告在全域的 f() 本體 int f(int x) { int res = x*2 - 1; return res; } ``` ## 回傳值 return value 函數的本體可透過 `return` 來回傳一個值作為計算結果, 一旦執行到 `return` 函數便會停止執行。 ```cpp= int divide(int p, int q) { if (q == 0) { cout << "NOOOOO you CANNOT divide 0!!\n"; return 0; cout << "after return 0, this won't be executed.\n"; } return p / q; } ``` 例如上述程式碼,在 q == 0 時便會因 `return 0;` 而結束執行, ## void 型別的函數 不回傳任何結果,可將型別宣告為 void。 它將不再能回傳任何值,也不能作為運算元參與計算。 仍然可以使用 return 結束函數執行,但不能回傳任何值。 ```cpp= void output(int t) { if (t < 0) { cout << "negative.\n"; // return 仍會結束執行,但不得傳回任何值,必須接著分號 ; return; } cout << "non-negative.\n"; } ``` 上述程式碼宣告一個型別為 void 的函數, 將只能執行,不會回報任何值,無法參與計算。 ```cpp= // compile error int a = output(-4); // 僅能呼叫不能參與計算 output(-4); ``` # 指標 **變數的記憶體位址。** &:取地址 *:解參考(存取該地址的值) ```cpp= int a = 10; int* p = &a; // p 存的是 a 的記憶體位置 cout << *p; // *p 代表「拿 p 指向的值」→ 輸出 10 ``` 用於 * 傳遞大量資料時避免複製 * 實作資料結構(linked list, tree) # 變數生命週期 ## 區域變數的遮蔽 shadowing 具有完全相同可見度和生命週期的變數,為免混淆不能取相同的名字; 但是不同的可以,範圍小的會遮蔽掉範圍大的。 因此,區域變數可以遮蔽全域變數, :::warning 而更小更新的區域變數,可以遮蔽更大更舊的。 ::: ```cpp= #include <iostream> using namespace std; int n; void gg(int t) { // 遮蔽全域的 n int n; n = t; n *= 2; cout << "gg " << n << '\n'; } int main() { cin >> n; cout << "n: " << n << '\n'; gg(n+5); cout << "n: " << n << '\n'; // 遮蔽全域的 n for (int n=1; n<=3; n++) { cout << "for n: " << n << '\n'; } // 脫離 n 的可見範圍,區域變數的 n 已消滅,被遮蔽的全域 n 重見天日 cout << "after n: " << n << '\n'; return 0; } ``` # lambda匿名函式 格式 ```cpp [capture](parameter) -> return_type { body } ``` > capture是 **捕捉變數**: 你可以抓外面的參數進來 ```cpp= int x = 10; auto f = [x](int y) { return x + y; }; // 捕捉 x 的值 cout << f(5); // 15 // 或用指標(下一章會說明) int x = 10; auto f = [&x](int y) { return x + y; }; x = 20; cout << f(5); // 25 ``` ## 常見用法 - sort 可以搭配sort函式,根據不同條件排序 > sort可搭配vector, pair做出超強組合技,後面會說到。 ```cpp= // 降冪排序 sort(nums.begin(), nums.end(), [](int a, int b) { return a > b; }); ```