最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++11可變參數(shù)模板詳解

 更新時(shí)間:2026年05月19日 10:00:29   作者:愚潤(rùn)澤  
這篇文章給大家介紹C++11可變參數(shù)模板詳解,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧

一,什么是可變參數(shù)模板

什么是可變?
可變就是可以不同??勺儏?shù),即:參數(shù)類型可變,參數(shù)個(gè)數(shù)可變。

  • C++11之前,類模板和函數(shù)模板中只能包含固定數(shù)量的模板參數(shù)
  • C++11新增了可變參數(shù)模板,讓我們可以對(duì)模板的參數(shù)高度泛化,即:可以直接傳一個(gè)參數(shù)包給模板參數(shù),這個(gè)參數(shù)包可以接受任意數(shù)量和任意類型的參數(shù)。

二,基本語法

使用 typename...class... 聲明模板參數(shù)包,...就代表是一個(gè)參數(shù)包:

template<typename T, typename... Args>
void myFunc(T first, Args... rest) { /*...*/ } // 使用模板的參數(shù)包
  • Args 是模板的類型參數(shù)包,表示接收一組類型
  • Args... rest 是函數(shù)參數(shù)包,表示使用Args類型,接收一組參數(shù)(后面要跟...)。它將模板參數(shù)包展開為一組函數(shù)參數(shù)
  • Args只是參數(shù)包的名字,可以取其他名字
  • 參數(shù)包代表可接收0個(gè)或多個(gè)參數(shù)

三,可變參數(shù)模板的使用

參數(shù)包作為整體

我們?cè)谑褂脮r(shí),可以往myFunc里傳入不同個(gè)數(shù)和不同類型的參數(shù)。
編譯器在編譯的過程中,根據(jù)myFunc傳入的不同參數(shù),實(shí)例化出帶有不同參數(shù)的myFunc函數(shù)
示例:

template<class ...Args>
void Myfunc(Args...args)
{
	cout << sizeof...(args) << endl;
}
int main()
{
	int x1 = 1;
	double x2 = 2.2;
	std::string s1 = "hello world";
	Myfunc(x1);  // 輸出:1
	Myfunc(x1, x2);  // 輸出:2
	Myfunc(x1, x2, s1);  // 輸出:3
	return 0;
}

說明:

  • 可以理解為,在編譯的時(shí)候,編譯器根據(jù)傳入的不同參數(shù)的Myfunc實(shí)例化出了三個(gè):Myfunc(int x1)、Myfunc(int x1, int x2)、Myfunc(int x1, int x2, string s1)
  • sizeof...(args)sizeof...是一個(gè)整體運(yùn)算符,用來求函數(shù)參數(shù)包中參數(shù)的個(gè)數(shù),這里的args就是一個(gè)整體,即:一組參數(shù)。

包展開

對(duì)于一個(gè)參數(shù)包,我們可以把他當(dāng)做一個(gè)整體進(jìn)行使用,如上面的sizeof...(args),我們就是直接把args當(dāng)一個(gè)整體進(jìn)行使用。

如果我們想要拿到里面的每一個(gè)參數(shù)就需要用到包展開。直接將參數(shù)包依次展開依次作為實(shí)參給?個(gè)函數(shù)去處理。
【注意,參數(shù)包可不能args[i]這樣下標(biāo)訪問使用。因?yàn)椋簠?shù)包是在編譯時(shí)就確定的一組參數(shù)。在編譯時(shí),編譯器會(huì)根據(jù)具體的模板實(shí)例化來處理參數(shù)包,而不像數(shù)組那樣在運(yùn)行時(shí)存在于內(nèi)存中】

錯(cuò)誤示范1(不能args[i])

假設(shè)你想打印出函數(shù)參數(shù)包里面的所有參數(shù)。

template<class ...Args>
void Print(Args...args)
{
	cout << args... << endl;
}

你這樣肯定不行,會(huì)報(bào)錯(cuò):“args”: 未聲明的標(biāo)識(shí)符。因?yàn)閰?shù)列表里面args在編譯時(shí)早就被具體實(shí)例化成了有具體類型的函數(shù)了,如Print(1.1, 2)就被實(shí)例化成:Print(double x1, int x2);

普通一次展開

在使用遞歸展開的時(shí)候,我們先來看一個(gè)簡(jiǎn)單的展開:

template<class T1, class T2, class...Args>
void ShowList(T1 x1, T2 x2, Args...args)
{
	cout << x1 << endl;
	cout << x2 << endl;
	cout << sizeof...(args) << endl;
}
int main()
{
	ShowList(1, 2.2, 3.3, "hello world");
	return 0;
}

輸出結(jié)果:

在這里,我們傳入一組參數(shù),其中1、2.2分別給了x1x2,后面的3.3"hello world"被打包給了args

遞歸展開

寫法三大要點(diǎn):

  • 遞歸終止函數(shù)
  • 遞歸的包展開函數(shù),參數(shù)列表為:(單個(gè)參數(shù),參數(shù)包)【這樣原來傳入的參數(shù)包,第一個(gè)參數(shù)會(huì)被提出來,第2 - n個(gè)參數(shù)會(huì)被作為新參數(shù)包】。然后在這個(gè)函數(shù)內(nèi),就可以對(duì)這個(gè)提出來的參數(shù)進(jìn)行操作
  • 外殼函數(shù),即:在遞歸函數(shù)外面封一層,用于把參數(shù)包傳給遞歸包展開函數(shù)

示例:
Print 打印出函數(shù)參數(shù)包里面的所有參數(shù)

// 遞歸終止函數(shù):當(dāng)參數(shù)列表為空時(shí)匹配這個(gè)函數(shù)
void ShowList()
{
	cout << endl;
}
// 遞歸包展開函數(shù)
template<class T, class...Args>
void ShowList(T x, Args...args)
{
	cout << x << " "; // 打印被展開的單個(gè)參數(shù)
	ShowList(args...);
}
template<class...Args>
void Print(Args... args)
{
	ShowList(args...);
}
int main()
{
	Print(1, string("xxxxx"), 2.2);
	return 0;
}
  • args......是包展開操作符
  • 在調(diào)用到ShowList的時(shí)候:最少傳入一個(gè)參數(shù)(因?yàn)橛袀€(gè) T x
  • 當(dāng)沒有參數(shù)傳入的時(shí)候,就會(huì)匹配到ShowList()結(jié)束

運(yùn)行結(jié)果:

1 xxxxx 2.2

具體編譯時(shí)實(shí)例化理解圖:

當(dāng)然也可以編寫有參的結(jié)束函數(shù):

//遞歸終止函數(shù)
template<class T>
void ShowList(T x)
{
	cout << x << endl;
}

當(dāng)ShowList參數(shù)個(gè)數(shù)為1的時(shí)候編譯器會(huì)找最匹配的,也就是調(diào)到這個(gè)ShowList(T x),然后執(zhí)行完以后,ShowList(T x)里面沒有再調(diào)用ShowList于是完成終止

錯(cuò)誤示范2(if運(yùn)行時(shí)判斷)

那在遞歸函數(shù)里面,利用sizeof...(args) == 0來終止可以嗎?
答案是不可以?。?!

template<class T, class ...Args>
void ShowList(T value, Args... args)
{
	cout << value << " "; //打印傳入的若干參數(shù)中的第一個(gè)參數(shù)
	if (sizeof...(args) == 0)
	{
		return;
	}
	ShowList(args...);    //將剩下參數(shù)繼續(xù)向下傳
}
int main()
{
	ShowList(1, 2.2, 3.3, "hello world");
	return 0;
}

報(bào)錯(cuò):“ShowList”: 未找到匹配的重載函數(shù)

為什么 if (sizeof...(args) == 0) 無法終止遞歸(以下內(nèi)容由AI生成):

1. sizeof...(args) 是編譯期常量,但 if 是運(yùn)行時(shí)判斷

  • sizeof...(args) 的值在編譯時(shí)就已經(jīng)確定(比如 args 有 3 個(gè)參數(shù)時(shí),sizeof...(args) 就是 3)。
  • if (sizeof...(args) == 0) 這個(gè) if 語句本身是運(yùn)行時(shí)執(zhí)行的,編譯器仍然會(huì) 生成所有分支的代碼,包括 ShowList(args...) 的調(diào)用。

2. 編譯器必須實(shí)例化 ShowList(args...)
即使 if 條件在運(yùn)行時(shí)是 false,編譯器仍然要 確保 ShowList(args...) 的調(diào)用是合法的,因?yàn)椋?/p>

  • C++ 的模板實(shí)例化規(guī)則要求 所有可能調(diào)用的模板函數(shù)都必須有定義。
  • 即使 if 條件保證 ShowList(args...) 不會(huì)執(zhí)行,編譯器仍然會(huì) 嘗試實(shí)例化它。

3. 當(dāng) args... 為空時(shí),ShowList() 無匹配版本

  • 當(dāng)遞歸到最后一步,args... 為空時(shí),ShowList(args...) 就變成了 ShowList()。
  • 但代碼 沒有定義 ShowList() 這個(gè)無參數(shù)版本,我們的ShowList(T value, Args... args),args可以為空,但是value必須給。所以編譯器報(bào)錯(cuò): error: no matching function for call to 'ShowList()'

解決方法:

方法1 : 像之前介紹的一樣,額外寫第一個(gè)終止函數(shù)。

if constexpr 編譯時(shí)判斷解決問題

方法 2:用 if constexpr(C++17 編譯時(shí)判斷)【已驗(yàn)證有效】

template<class T, class... Args>
void ShowList(T value, Args... args) {
    cout << value << " ";
    if constexpr (sizeof...(args) > 0) {  // 編譯時(shí)判斷
        ShowList(args...);               // 僅在 args 非空時(shí)實(shí)例化
    }
    // 否則自動(dòng)終止
}
  • if constexpr 是編譯期判斷,不會(huì)生成無效的 ShowList() 調(diào)用。

非遞歸展開

示例:

template <class T>
const T& GetArg(const T& x) {
    cout << x << " ";  // 打印參數(shù)
    return x;          // 返回原參數(shù)(保證類型不變)
}
template <class ...Args>
void Arguments(Args... args) {}  // 空函數(shù),僅用于接收展開后的參數(shù)包
template <class ...Args>
void Print(Args... args) {
    Arguments(GetArg(args)...);  // 關(guān)鍵:展開參數(shù)包并調(diào)用 GetArg 處理每個(gè)參數(shù)
}
int main()
{
    Print(1, 2.2, 3.3, "hello world");
    return 0;
}
  • GetArg參數(shù)包展開及使用函數(shù)
    • GetArg(args)......讓編譯器遍歷args的每一個(gè)參數(shù),并對(duì) 每一個(gè)參數(shù) 調(diào)用 GetArg,相當(dāng)于: Arguments(GetArg(arg1), GetArg(arg2), ..., GetArg(argN));
    • GetArg必須要有返回值,用于讓Arguments 接收到參數(shù)
  • Arguments 空函數(shù)
    • 僅用于 接收展開后的參數(shù)包,確保 GetArg(args)... 能正確展開。
    • 在 C++ 中,參數(shù)包展開GetArg(args)...必須發(fā)生在合法的上下文環(huán)境中,Arguments(GetArg(args)...) 提供的就是這樣一個(gè)上下文?!究梢岳斫鉃?,就需要一個(gè)能接受參數(shù)包的容器來接收GetArg(args)...的返回值】

到此這篇關(guān)于C++11可變參數(shù)模板的文章就介紹到這了,更多相關(guān)C++11可變參數(shù)模板內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語言深入探究選擇排序與基數(shù)排序使用案例講解

    C語言深入探究選擇排序與基數(shù)排序使用案例講解

    算法中排序是十分重要的,而每一個(gè)學(xué)習(xí)計(jì)算機(jī)的都會(huì)在初期的時(shí)候接觸到這種排序,下面這篇文章主要給大家介紹了關(guān)于c語言選擇排序與基數(shù)排序使用的相關(guān)資料,需要的朋友可以參考下
    2022-05-05
  • Gstreamer基礎(chǔ)知識(shí)教程

    Gstreamer基礎(chǔ)知識(shí)教程

    由于deepstream是基于gstreamer的,所以要想在deepstream上做拓展,需要對(duì)gstreamer有一定的認(rèn)識(shí),以下主要介紹Gstreamer整體框架和Gstreamer基礎(chǔ)概念,需要的朋友可以參考下
    2022-07-07
  • C++圖書管理系統(tǒng)程序源代碼

    C++圖書管理系統(tǒng)程序源代碼

    這篇文章主要為大家詳細(xì)介紹了C++圖書管理系統(tǒng)程序源代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • Qt與QWebEngineView交互完整參考示例代碼

    Qt與QWebEngineView交互完整參考示例代碼

    QWebEngineView是Qt框架中的一個(gè)組件,它是基于Chromium內(nèi)核的Web瀏覽器引擎,用于在Qt應(yīng)用程序中嵌入網(wǎng)頁內(nèi)容和實(shí)現(xiàn)各種Web應(yīng)用功能,這篇文章主要給大家介紹了關(guān)于Qt與QWebEngineView交互完整參考的相關(guān)資料,需要的朋友可以參考下
    2024-07-07
  • c++實(shí)現(xiàn)一個(gè)簡(jiǎn)易的網(wǎng)絡(luò)緩沖區(qū)的實(shí)踐

    c++實(shí)現(xiàn)一個(gè)簡(jiǎn)易的網(wǎng)絡(luò)緩沖區(qū)的實(shí)踐

    這篇文章主要介紹了c++實(shí)現(xiàn)一個(gè)簡(jiǎn)易的網(wǎng)絡(luò)緩沖區(qū)的實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • C語言入門篇--函數(shù)及數(shù)組用法

    C語言入門篇--函數(shù)及數(shù)組用法

    本篇文章是c語言基礎(chǔ)篇,主要為大家介紹了C語言的函數(shù)與數(shù)組,每個(gè)函數(shù)本質(zhì)上都實(shí)現(xiàn)一個(gè)最小的功能,而main函數(shù)只負(fù)責(zé)調(diào)用函數(shù),實(shí)現(xiàn)代碼的核心邏輯,提高代碼的可維護(hù)性
    2021-08-08
  • VSCode配置C/C++環(huán)境的最新詳細(xì)教程

    VSCode配置C/C++環(huán)境的最新詳細(xì)教程

    VisualStudioCode(簡(jiǎn)稱VSCode)是Microsoft開發(fā)的代碼編輯器,它支持Windows,Linux和macOS等操作系統(tǒng)以及開源代碼,下面這篇文章主要給大家介紹了關(guān)于VSCode配置C/C++環(huán)境的最新詳細(xì)教程,需要的朋友可以參考下
    2022-12-12
  • C++的四種類型轉(zhuǎn)換

    C++的四種類型轉(zhuǎn)換

    這篇文章主要介紹了C++的四種類型轉(zhuǎn)換,有詳細(xì)的示例代碼展示,對(duì)于學(xué)習(xí)C++的同學(xué)有一定的參考價(jià)值,感興趣的同學(xué)可以參考本文
    2023-04-04
  • C語言模擬實(shí)現(xiàn)密碼輸入的示例代碼

    C語言模擬實(shí)現(xiàn)密碼輸入的示例代碼

    本文主要介紹了C語言模擬實(shí)現(xiàn)密碼輸入的示例代碼,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • Qt編寫地圖綜合應(yīng)用之繪制雨量分布

    Qt編寫地圖綜合應(yīng)用之繪制雨量分布

    雨量分布圖是在區(qū)域地圖基礎(chǔ)上,針對(duì)區(qū)域中的每個(gè)最小單位區(qū)域比如縣城點(diǎn)位不同顏色顯示。本文將詳細(xì)為大家介紹如何通過QT編寫繪制雨量分布,感興趣的小伙伴可以了解一下
    2021-12-12

最新評(píng)論

南汇区| 高雄市| 天长市| 海宁市| 册亨县| 庆安县| 花莲市| 会东县| 青河县| 乌鲁木齐市| 章丘市| 二连浩特市| 临海市| 肥西县| 塔城市| 开鲁县| 高邮市| 潮州市| 襄樊市| 霍山县| 天柱县| 阳西县| 花莲市| 高雄市| 克山县| 米脂县| 无锡市| 措勤县| 黄梅县| 濉溪县| 读书| 商河县| 云浮市| 镶黄旗| 含山县| 鄂托克旗| 马龙县| 三江| 伊通| 民勤县| 陆河县|