C++可變參數

  • 可變參數
    • C風格的可變參數
      • C風格可變參數的使用
    • C++11可變參數模板
      • 遞歸展開參數包
      • 參數列表展開
      • 折疊表達式
    • STL中的emplace插入接口

可變參數

C風格的可變參數

可變參數是一種語言特性,可以在函數聲明中使用省略號...來表示函數接受可變數量的參數。

例如典型的printf()函數:

int printf (const char * szFormat, ...);// printf("%d + %d = %d \n", 1, 2, 1+2);

第一個參數是格式化字符串,后面的...是可變參數

//使用宏定義與可變參數
//__VA_ARGS__表示宏定義中的可變參數部分
#define LOG(format, ...) printf(format, ##__VA_ARGS__)

如果可變參數列表為空,## 會刪除前面的逗號,避免語法錯誤


C風格可變參數的使用

在函數體內,可以使用 va_list 類型的變量和va_start, va_arg, va_end,函數來處理可變參數。

<stdarg.h> 頭文件中包含

請添加圖片描述請添加圖片描述
請添加圖片描述
請添加圖片描述


paramN : 函數定義中最后一個命名參數的名稱。隨后調用va_arg提取的參數是后面的參數


示例:

void my_printf(const char* format,...)
{//定義一個va_list類型變量va_list argList; 	//初始化argList,獲取format后面的額外參數va_start(argList, format);	//依次獲取可變的參數值。需要指定參數值的數據類型while (*format != '\0') {if(*format == '%') {format++;            switch (*format) {case 'd': //整數                   cout << va_arg(argList, int) << " ";break;case 'f': //浮點數                  cout << va_arg(argList, double) << " ";break;}}format++;}//釋放va_list變量va_end(argList);
}my_printf("%d, %f", 25, 3.22);

C++11可變參數模板

C++11新增特性。可變參數模板是一種用于處理具有不定數量參數的函數模板的特性。

定義:

template<class ...Args>
viod func(Args... args);

Args為參數包名,前加可變參數...進行聲明。參數包中可以包含0~n個不同類型參數


通過使用參數包展開表達式,才能獲取并使用參數

遞歸展開參數包

示例:

//當遞歸展開介紹,調用該終止函數
int sum() {return 0;
}// 遞歸情況:將第一個參數與后面的參數相加
template<typename T, typename... Args>
T sum(T first, Args... rest) {return first + sum(rest...);
}std::cout << sum(1, 2, 3, 4, 5) << std::endl; // 輸出:15
std::cout << sum(10.5, 20.5, 30.5) << std::endl; // 輸出:61.5

使用參數包時,需要加上展開操作符...

遞歸展開時,需要注意,如果沒有終止函數,當參數包中的參數個數為0后,會發生死循環

上述代碼的終止函數也可以寫一下形式:

//當沒有參數時,返回0
template<typename T>
T sum(T value) {return value;
}

參數列表展開

通過參數列表(initializer_list)獲取參數包中的參數

如果參數包中的各個參數都是相同類型,這可以通過列表初始化的形式,將其轉移到數組中。

template<typename... Args>
void func(Args... args) {    int dummy[] = { args...};dummy[0];//使用...
}

該操作,不支持0個參數的參數包(不能分配常量大小為0的數組)


對于不同類型的參數,可以利用參數列表結合逗號表達式,將參數包展開為逗號分隔的一系列獨立的參數。

template<class T>
void doSomething(const T& t)
{...//使用
}template<typename... Args>
void myFunction(Args... args) {// 使用展開操作符將參數包展開int arr[] = { (doSomething(args), 0)...};// ...
}

通過初始化列表來初始化一個變長數組,然后再對數組arr初始化時,會執行expand函數中的逗號表達式(從左到右計算表達式并將最后一個表達式的值返回)。最終會在創建完一個int arr[sizof ...args] = {0}的數組同時,處理參數包中的參數。

當然這里的int型以及逗號表達式中的0值,都沒有后續的使用意義。

myFunction(1, 2.5, "hello");//參數包展開為:
int arr[] = {(doSomething(1), 0),(doSomething(2.5), 0),(doSomething("hello"), 0)
};

如果不想在0個參數時 myFunction();,編譯報錯,可增加無參的重載

//可增加一個無參的函數重載,來對0個參數特殊處理
void doSomething();

折疊表達式

折疊表達式(Fold Expressions) 是 C++17 引入的一種簡化可變參數模板(variadic templates)的語法特性。

有四種:

(pack op ...)			// 一元左折疊
(... op pack)			// 一元右折疊
(init op ... op pack)	// 二元左折疊
(pack op ... op init)	// 二元右折疊

使用:

template<typename... Args>
auto sum(Args... args) {return (args + ...); // 一元左折疊
}sum(1,2,3,4); // (((1 + 2) + 3) + 4)
template<typename... Args>
auto sum(Args... args) {return (... + args); // 一元右折疊
}sum(1,2,3,4); // (1 + (2 + (3 + 4)))
template<typename... Args>
auto sum_with_init(int init, Args... args) {return (init + ... + args); // 二元左折疊
}sum_with_init(0,1,2,3); // (((0 + 1) + 2) + 3)
template<typename... Args>
auto sum_with_init(int init, Args... args) {return (args + ... + init); // 二元右折疊
}sum_with_init(0,1,2,3); // (1 + (2 + (3 + 10)))

template<typename... Args>
void myFunction(Args... args) {(doSomething(args), ...); // 折疊表達式
}myFunction(1, 2.5, "hello"); 
// (doSomething(1), (doSomething(2.5), (doSomething("hello"))));
  • pack : args
  • op : ,

STL中的emplace插入接口

例如在vector容器中:
請添加圖片描述

該成員函數,就是使用了可變參數模板,使用上和原來的插入接口push_back差別不大

vector<std::pair<int, string>> v;
v.push_back(make_pair( 0, "hello" ));
v.emplace_back(1, "world");

make_pair會多構建一次string對象的消耗


🦀🦀觀看~~

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/73409.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/73409.shtml
英文地址,請注明出處:http://en.pswp.cn/web/73409.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

數據庫的操作,以及sql之DML

首先&#xff0c;創建表以及插入數據 create table t_text(id int primary key auto_increment,name varchar(20) unique not null,gender char(5) not null check(gender in ("男","女")),deed varchar(255) not null default "事例不詳"); in…

vue2前端日志數據存儲(indexedD)自動清理3天前的數據

前言&#xff1a;關于Dexie.js這個前端本地數據庫&#xff0c;如何使用IndexedDB來存儲數據&#xff0c;并且設置到期自動清理的機制。首先&#xff0c;我需要回憶一下Dexie.js的基本用法&#xff0c;以及IndexedDB的特性。IndexedDB是瀏覽器中的一種非關系型數據庫&#xff0c…

【MySQL篇】索引特性,索引的工作原理以及索引的創建與管理

目錄 一&#xff0c;初識索引 二&#xff0c;MySQL與磁盤交互的基本單位 三&#xff0c;MySQL中數據文件的特性 四&#xff0c;理解page和索引 五&#xff0c;聚簇索引和非聚簇索引 六&#xff0c;索引操作 查詢索引 創建主鍵索引 唯一索引的創建 普通索引的創建 全文…

springboot項目啟動常見的問題以及配置以及一些使用技巧

1.配置倉庫 這里要把xml文件從國外的鏡像源改成國內的鏡像源。改鏡像源可以查看這篇文章 點擊查看 2.更改文件類型 方法一&#xff1a;右鍵文件找到Mark Dircetory as可以更改文件類型 方法二&#xff1a; 3.springboot本地Maven倉庫的位置 4.pom.xml文件報紅錯誤怎么辦 這…

【初探數據結構】二叉樹的順序結構——堆的實現詳解(上下調整算法的時間復雜度分析)

&#x1f4ac; 歡迎討論&#xff1a;在閱讀過程中有任何疑問&#xff0c;歡迎在評論區留言&#xff0c;我們一起交流學習&#xff01; &#x1f44d; 點贊、收藏與分享&#xff1a;如果你覺得這篇文章對你有幫助&#xff0c;記得點贊、收藏&#xff0c;并分享給更多對數據結構感…

流量分析2

一&#xff0c;webshell流量 [GKCTF 2021]簽到 先看協議分級&#xff0c;大部分是tcp&#xff0c;里面有http的基于的行文本數據占了很大的比重&#xff0c;看看里面有什么 過濾http的流量 點擊一條流量&#xff0c;里面的內容進去后面有基于行的文本數據&#xff0c; 先解he…

頭歌實踐教學平臺--【數據庫概論】--SQL

一、表結構與完整性約束的修改(ALTER) 1.修改表名 USE TestDb1; alter table your_table rename TO my_table; 2.添加與刪除字段 #語句1&#xff1a;刪除表orderDetail中的列orderDate alter table orderDetail drop orderDate; #語句2&#xff1a;添加列unitPrice alter t…

在 React 中,組件之間傳遞變量的常見方法

目錄 1. **通過 Props 傳遞數據**2. **通過回調函數傳遞數據**3. **通過 Context API 傳遞數據**4. **通過 Redux 管理全局狀態**5. **通過事件總線&#xff08;如 Node.js 的 EventEmitter&#xff09;**6. **通過 Local Storage / Session Storage**7. **通過 URL 查詢參數傳…

Redis + 布隆過濾器解決緩存穿透問題

Redis 布隆過濾器解決緩存穿透問題 1. Redis 布隆過濾器解決緩存穿透問題 &#x1f4cc; 什么是緩存穿透&#xff1f; 緩存穿透指的是查詢的數據既不在緩存&#xff0c;也不在數據庫&#xff0c;導致每次查詢都直接訪問數據庫&#xff0c;增加數據庫壓力。 例如&#xff1…

Vue動態添加或刪除DOM元素:購物車實例

Vue 指令系列文章: 《Vue插值:雙大括號標簽、v-text、v-html、v-bind 指令》 《Vue指令:v-cloak、v-once、v-pre 指令》 《Vue條件判斷:v-if、v-else、v-else-if、v-show 指令》 《Vue循環遍歷:v-for 指令》 《Vue事件處理:v-on 指令》 《Vue表單元素綁定:v-model 指令》…

vue h5實現車牌號輸入框

哈嘍&#xff0c;大家好&#xff0c;最近鵬仔開發的項目是學校校內車輛超速方面的統計檢測方面的系統&#xff0c;在開發過程中發現有個小功能&#xff0c;就是用戶移動端添加車牌號&#xff0c;剛開始想著就一個輸入框&#xff0c;提交時正則效驗一下格式就行&#xff0c;最后…

硬件基礎(5):(3)二極管的應用

文章目錄 [toc]1. **整流電路****功能**&#xff1a;**工作原理**&#xff1a;**應用實例**&#xff1a;電路組成&#xff1a;整流過程&#xff1a;電路的應用&#xff1a; 2. **穩壓電路****功能**&#xff1a;**工作原理**&#xff1a;**應用實例**&#xff1a;電路組成及功能…

Wireshark網絡抓包分析使用詳解

序言 之前學計網還有前幾天備考華為 ICT 網絡賽道時都有了解認識 Wireshark&#xff0c;但一直沒怎么專門去用過&#xff0c;也沒去系統學習過&#xff0c;就想趁著備考的網絡相關知識還沒忘光&#xff0c;先來系統學下整理點筆記~ 什么是抓包&#xff1f;抓包就是將網絡傳輸…

安心聯車輛管理平臺源碼價值分析

安心聯車輛管理平臺源碼的價值可從技術特性、功能覆蓋、市場適配性、擴展潛力及商業化支持等多個維度進行分析。以下結合實際應用進行詳細解讀&#xff1a; 一、技術架構與開發優勢 主流技術棧與高性能架構 源碼采用成熟的前后端分離架構&#xff0c;后端基于Java技術&#xff…

【操作系統】Docker如何使用-續

文章目錄 1、概述2、鞏固知識2.1、基礎命令2.2、容器管理2.3、鏡像管理2.4、網絡管理2.5、Compose 3、常用命令 1、概述 在使用Docker的過程中&#xff0c;掌握常用的命令是至關重要的。然而&#xff0c;隨著時間的推移&#xff0c;我們可能會遺忘一些關鍵的命令或對其用法變得…

ElementUI el-menu導航開啟vue-router模式

有沒有小伙伴遇到這么一種情況&#xff1a;ElementUI el-menu導航中&#xff0c;開啟vue-router 的模式后&#xff0c;點擊觸發事件而不進行路由跳轉&#xff1f; 別慌&#xff01;下面直接說解決方案&#xff1a; 借助路由守衛進行判斷 給el-menu綁定切換事件&#xff0c;給…

【leetcode hot 100 17】電話號碼的字母組合

分析&#xff1a;當設計關鍵字“所有組合”時&#xff0c;要考慮深度優先遍歷、廣度優先遍歷&#xff08;層次遍歷&#xff09;&#xff0c;其中&#xff1a; 深度優先搜索&#xff1a; 自頂向下的遞歸實現深搜定義子問題在當前遞歸層結合子問題結果解決原問題 廣度優先搜索 利…

Vue 2 探秘:visible 和 append-to-body 是誰的小秘密?

&#x1f680; Vue 2 探秘&#xff1a;visible 和 append-to-body 是誰的小秘密&#xff1f;&#x1f914; 父組件&#xff1a;identify-list.vue子組件&#xff1a;fake-clue-list.vue 嘿&#xff0c;各位前端探險家&#xff01;&#x1f44b; 今天我們要在 Vue 2 的代碼叢林…

C++學習之路:從頭搞懂配置VScode開發環境的邏輯與步驟

目錄 編輯器與IDE基于vscode的C開發環境配置1. 下載vscode、淺嘗編譯。番外篇 2. 安裝插件&#xff0c;賦能編程。3. 各種json文件的作用。c_cpp_properties.jsontask.jsonlaunch.json 總結&&彩蛋 編輯器與IDE 上一篇博客已經介紹過了C程序的一個編譯流程&#xff0c;從…

PPT 轉高精度圖片 API 接口

PPT 轉高精度圖片 API 接口 文件處理 / 圖片處理&#xff0c;將 PPT 文件轉換為圖片序列。 1. 產品功能 支持將 PPT 文件轉換為高質量圖片序列&#xff1b;支持 .ppt 和 .pptx 格式&#xff1b;保持原始 PPT 的布局和樣式&#xff1b;轉換后的圖片支持永久訪問&#xff1b;全…