網站首頁 編程語言 正文
一、基礎
函數:封裝了一段代碼,可以在一次執行過程中被反復調用,包含函數頭和函數體;
函數頭:
- 函數名稱(標識符),用于后續的調用;
- 形式參數,代表函數的輸入參數;
- 返回類型,函數執行完成后返回結果的類型;
函數體:一個語句塊(block
),包含具體的計算邏輯;
函數的聲明與定義:
- 函數聲明只包含函數頭,不包含函數體,通常在頭文件中;
- 函數聲明可以出現多次,定義通常出現一次(也有例外);
函數調用:
- 需要提供函數名與實際參數;
- 實際參數拷貝初始化給形式參數;
- 返回值會拷貝給函數的調用者;
- 棧幀結構(可自行了解下);
二、參數
對于非模板函數來說,其每個形參都有確定的類型,但形參可以沒有名稱;
實參到形參的拷貝順序是不確定的;
函數的形參的傳遞一般分為:傳值、傳址、傳引用;
變長參數的定義:
1、使用initializer_list傳遞
#include <initializer_list> void fun(std::initializer_list<int> a){} int main { fun({1, 2, 3, 4}) }
注意:該方法只能傳遞類型相同的變長參數;
- 可變長度模板參數
- 使用省略號表示形式參數(一般不使用)
函數的缺省實參注意點:
1、如果某個形參具有缺省參數,那么它右側的形參都必須具有缺省實參;
void fun(int x=1, int y=2){} // 這里y必須給定缺省值
2、具有缺省實參的函數調用時,傳入實參按照從左到右的順序進行匹配;
3、在一個翻譯單元中,每個形參的缺省實參只能定義一次;
4、缺省實參為對象時,實參的缺省值會隨對象值的變化而變化;
main函數的版本:
- 無形參版本(一般使用)
- 帶形參版本
int main(int argc, char *argv[]) {}
argc
是非負數,表述傳入參數個數,argv是一個指針指向傳輸參數的數組頭。
三、返回類型
返回類型的幾種書寫方式:
經典方法:位于函數頭的前部,也是最常規的寫法;
C++11引入的方式:位于函數頭的尾部;
auto fun(int x) -> int { return x*2; }
C++14引入的方式:返回類型的自動推導;
auto fun(int a) { return a; // 會根據return語句進行推導 }
四、函數重載與解析
函數重載:使用相同的函數名定義多個函數,每個函數具有不同的參數列表;
注意:不能基于不同的返回類型進行重載;
名稱查找:
- 分為限定查找和非限定查找:有無限定在某個作用域中;
- 非限定查找會進行域的逐級查找——名稱隱藏;
- 查找通常只會在已聲明的名稱集合中進行;
重載解析:在名稱查找的基礎上進一步選擇合適的調用函數;
-
過濾不能被調用的版本:參數個數不對、無法將實參轉為形參、實參不滿足形參的限制條件;
五、內聯函數
定義:將比較簡單的函數邏輯展開到調用函數的部分,避免棧幀銷毀,提升性能;
關鍵字:inline
,如果一個函數在多個翻譯單元展開,加入這個關鍵字可以避免重復定義;
1.constexpr函數
定義:之前有介紹常量表達式時用到了該關鍵字,現在對于函數也可以用該關鍵字;
作用:使得函數在編譯器被執行,當然在有變量情況下也可在運行期執行;
constexpr int fun(int x){ // int y; std::cin >> y; 會報錯,該語句需要用戶傳入參數,只能在運行期執行 return x * 2; } int main { constexpr int x = fun(2); // 編譯器會翻譯成 move eax 4, 去掉constexpr也可以 return x; }
注意:constexpr
函數中的語句必須是可以在編譯器執行的語句;
拓展:關鍵字consteval
(C++20引入),函數只能在編譯器執行;
六、函數指針
作用:可以用于高階函數中,將函數指針作為參數;
代碼案例:
int add(x) { return x + 1}; using T = int(int); int fun(K* F, int x) { int tmp = (*F)(x); return tmp * 2; } int main { std::cout << fun(&add, 50) << std::endl; }
說明:這就是用函數指針定義的一個高階函數,在之后的很多高階函數、泛型算法中也是這樣的用法;
注意:當函數對象進行賦值或者返回值時,返回的是一個函數指針類型的對象;
七、思考
1、我們常常會見到如下代碼,是由什么作用?
extern "C" int fun(int x, int y) { return x + y; }
C語言對于函數是不能重載的,當用C調用C++程序時,往往找不到C++編譯后的函數名,可通過如上代碼定義一個函數為C類型函數;
2、可以用別名定義一個函數類型嗎?
using X = int[3]; X a; // 這是定義了一個數組,同int a[3] using X = int(int); X fun; // 這是定義了一個int返回類型的函數
函數也是有類型的,可以用別名定義,并且函數類型不包含形參名稱,并且只能聲明,不能定義;
總結:
本篇主要介紹了函數的基礎概念以及一些特殊的函數方法和類型。重點需要注意的就是函數重載以及函數指針,這個在后續的模板以及泛型編程都會用到;下一篇將討論C++中的內存,也是最重要的一個部分。
原文鏈接:https://blog.csdn.net/weixin_40620310/article/details/121600420
相關推薦
- 2022-09-05 Shiro 和 Spring Security 的比較
- 2022-05-14 pytorch中with?torch.no_grad():的用法實例_python
- 2023-08-15 vite打包報錯 Rollup failed to resolve
- 2023-10-09 對Uni-app進行原生開發
- 2022-11-23 Python字符串格式化實例講解_python
- 2022-03-03 el-form動態表單切換導致的校驗bug(v-if、v-show導致校驗失效的bug)
- 2023-01-28 架構師說比起404我們更怕200錯誤_相關技巧
- 2022-05-31 Android實現調用手機攝像頭錄像限制錄像時長_Android
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支