国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【C++】C++11可變參數(shù)模板

這篇具有很好參考價(jià)值的文章主要介紹了【C++】C++11可變參數(shù)模板。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

【C++】C++11可變參數(shù)模板,C++,c++,開(kāi)發(fā)語(yǔ)言

??樊梓慕:個(gè)人主頁(yè)

???個(gè)人專欄:《C語(yǔ)言》《數(shù)據(jù)結(jié)構(gòu)》《藍(lán)橋杯試題》《LeetCode刷題筆記》《實(shí)訓(xùn)項(xiàng)目》《C++》《Linux》《算法》

??每一個(gè)不曾起舞的日子,都是對(duì)生命的辜負(fù)


目錄

前言

可變參數(shù)模板的定義方式

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

編譯時(shí)遞歸展開(kāi)參數(shù)包

可變參數(shù)模板的應(yīng)用:emplace系列函數(shù)

對(duì)比emplace_back與push_back

emplace系列真正的優(yōu)勢(shì)在于淺拷貝的類(lèi)

總結(jié)

List類(lèi)增添模擬實(shí)現(xiàn)emplace系列函數(shù)

構(gòu)造

emplace_back()

emplace()


前言

其實(shí)我們之前經(jīng)常使用可變參數(shù)模板,C語(yǔ)言的printf函數(shù)大家一定非常熟悉,其實(shí)這就是一種可變參數(shù)模板:

【C++】C++11可變參數(shù)模板,C++,c++,開(kāi)發(fā)語(yǔ)言

那么在C++11引入可變參數(shù)模板的設(shè)計(jì)可以帶來(lái)什么變化呢?讓我們一起來(lái)學(xué)習(xí)下吧!?


歡迎大家??收藏??以便未來(lái)做題時(shí)可以快速找到思路,巧妙的方法可以事半功倍。?

=========================================================================文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-846316.html

GITEE相關(guān)代碼:??樊飛 (fanfei_c) - Gitee.com??

=========================================================================


可變參數(shù)模板的定義方式

template<class ...Args>
返回類(lèi)型 函數(shù)名(Args... args)
{
??//函數(shù)體
}

例如:

// Args是一個(gè)模板參數(shù)包,args是一個(gè)函數(shù)形參參數(shù)包
// 聲明一個(gè)參數(shù)包Args...args,這個(gè)參數(shù)包中可以包含0到任意個(gè)模板參數(shù)。
template <class ...Args>
void ShowList(Args... args)
{}
  • 模板參數(shù)Args前面有『 省略號(hào)』,代表它是一個(gè)可變模板參數(shù),我們把帶省略號(hào)的參數(shù)稱為參數(shù)包,參數(shù)包里面可以包含0到任意個(gè)模板參數(shù),而args則是一個(gè)函數(shù)形參參數(shù)包。
  • 模板參數(shù)包Args和函數(shù)形參參數(shù)包args的名字可以任意指定,并不是說(shuō)必須叫做Args和args,判斷是否為參數(shù)包的主要關(guān)鍵在『 省略號(hào)』。

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

此時(shí)我們可以傳入任意多個(gè)參數(shù)了,并且這些參數(shù)可以是不同類(lèi)型的:

int main()
{
?? ?ShowList();
?? ?ShowList(1);
?? ?ShowList(1, 'A');
?? ?ShowList(1, 'A', string("hello"));
?? ?return 0;
}

我們可以在函數(shù)模板中通過(guò)sizeof計(jì)算參數(shù)包中參數(shù)的個(gè)數(shù):

template<class ...Args>
void ShowList(Args... args)
{
?? ?cout << sizeof...(args) << endl; //獲取參數(shù)包中參數(shù)的個(gè)數(shù)
}

但是,我們?nèi)绾谓馕鰠?shù)包中的內(nèi)容呢?

我們可不可以這樣獲?。?/p>

template<class ...Args>
void ShowList(Args... args)
{

?? ?for (int i = 0; i < sizeof...(args); i++)
?? ?{
?? ??? ?cout << args[i] << " ";
?? ?}
?? ?cout << endl;
}

答案是不可以!

注意:可變參數(shù)模板,既然是模板就是編譯時(shí)解析,就不能使用如上這種運(yùn)行時(shí)解析的邏輯獲取。

因此要獲取參數(shù)包中的各個(gè)參數(shù),可以通過(guò)『 編譯時(shí)遞歸』的方式解析數(shù)據(jù)。


編譯時(shí)遞歸展開(kāi)參數(shù)包

如何實(shí)現(xiàn)編譯時(shí)遞歸呢?那肯定是利用編譯器的解析機(jī)制,我們給函數(shù)模板增加一個(gè)模板參數(shù),每次從接收到的參數(shù)包中剝離出來(lái)一個(gè)參數(shù),然后在函數(shù)模板中遞歸調(diào)用該函數(shù)模板,調(diào)用時(shí)傳入剩下的參數(shù)包,如此遞歸下去,每次剝離出參數(shù)包中的一個(gè)參數(shù),直到參數(shù)包中的所有參數(shù)都被取出來(lái)。

比如:

//展開(kāi)函數(shù)
template<class T, class ...Args>
void _ShowList(T value, Args... args)
{
	cout << value << " "; 
	_ShowList(args...);//遞歸
}

那么如何終止遞歸呢?

我們每次都剝離下一個(gè)參數(shù),最后必然就沒(méi)有參數(shù)了,那么根據(jù)編譯器的『最匹配原則 』,我們可以實(shí)現(xiàn)一個(gè)『 無(wú)參』的遞歸終止函數(shù):

//遞歸終止函數(shù)
void _ShowList()
{
	cout << endl;
}
//展開(kāi)函數(shù)
template<class T, class ...Args>
void _ShowList(T value, Args... args)
{
	cout << value << " ";
	_ShowList(args...);    //遞歸
}

然后再封裝起來(lái)如下:

//遞歸終止函數(shù)
void _ShowList()
{
	cout << endl;
}
//展開(kāi)函數(shù)
template<class T, class ...Args>
void _ShowList(T value, Args... args)
{
	cout << value << " "; //打印傳入的若干參數(shù)中的第一個(gè)參數(shù)
	_ShowList(args...); //將剩下參數(shù)繼續(xù)向下傳
}
//供外部調(diào)用的函數(shù)
template<class ...Args>
void ShowList(Args... args)
{
	_ShowList(args...);
}

這種『 編譯時(shí)遞歸』的思想可謂是非常新奇,值得我們學(xué)習(xí)。


可變參數(shù)模板的應(yīng)用:emplace系列函數(shù)

對(duì)比emplace_back與push_back

【C++】C++11可變參數(shù)模板,C++,c++,開(kāi)發(fā)語(yǔ)言

【C++】C++11可變參數(shù)模板,C++,c++,開(kāi)發(fā)語(yǔ)言

還記得么?

&&這里為萬(wàn)能引用,不是單純的右值引用。

?相對(duì)于push_back,emplace_back支持萬(wàn)能引用和可變參數(shù)模板。

他們都是尾插『 一個(gè)』數(shù)據(jù),注意這里不要看可變參數(shù)模板就以為是插入幾個(gè)值,這里是『 類(lèi)型』。

對(duì)比push_back與emplace_back:

int main()
{
	std::list<pair<F::string, F::string>> lt2;
	pair<F::string, F::string> kv1("xxxx", "yyyy");
	lt2.push_back(kv1);
	lt2.push_back(move(kv1));
	cout << "=============================================" << endl;

	pair<F::string, F::string> kv2("xxxx", "yyyy");
	lt2.emplace_back(kv2);
	lt2.emplace_back(move(kv2));
	cout << "=============================================" << endl;

	return 0;
}

對(duì)比發(fā)現(xiàn)也沒(méi)有區(qū)別?

【C++】C++11可變參數(shù)模板,C++,c++,開(kāi)發(fā)語(yǔ)言

其實(shí)emplace_back和push_back真正的區(qū)別在于:

push_back需要先用參數(shù)構(gòu)造pair這個(gè)對(duì)象,然后再將這個(gè)對(duì)象拷貝給鏈表節(jié)點(diǎn)中的pair;

而emplace_back是直接拿著參數(shù)去構(gòu)造鏈表節(jié)點(diǎn)中的pair,中間省略了拷貝的過(guò)程;

比如:

int main()
{
	std::list<pair<F::string, F::string>> lt2;
	pair<F::string, F::string> kv1("xxxx", "yyyy");
	lt2.push_back(kv1);
	lt2.push_back(move(kv1));
	cout << "=============================================" << endl;

	pair<F::string, F::string> kv2("xxxx", "yyyy");
	lt2.emplace_back(kv2);
	lt2.emplace_back(move(kv2));
	cout << "=============================================" << endl;

	lt2.emplace_back("xxxx", "yyyy");
	cout << "=============================================" << endl;
	return 0;
}

【C++】C++11可變參數(shù)模板,C++,c++,開(kāi)發(fā)語(yǔ)言


emplace系列真正的優(yōu)勢(shì)在于淺拷貝的類(lèi)

因?yàn)閷?duì)于深拷貝的且實(shí)現(xiàn)了移動(dòng)構(gòu)造的類(lèi)來(lái)說(shuō),移動(dòng)構(gòu)造代價(jià)很小,emplace的優(yōu)勢(shì)顯現(xiàn)不出來(lái)。

比如:

int main()
{
	std::list<F::string> lt1;
	lt1.push_back("xxxx");

	cout << "=============================================" << endl;

	lt1.emplace_back("xxxx");
	return 0;
}

【C++】C++11可變參數(shù)模板,C++,c++,開(kāi)發(fā)語(yǔ)言

emplace真正的優(yōu)勢(shì)在于淺拷貝的類(lèi),可以節(jié)省一個(gè)拷貝過(guò)程:

比如日期類(lèi):

class Date
{
public:
	//構(gòu)造
	Date(int year, int month, int day)
		:_year(year)
		, _month(month)
		, _day(day)
	{
		cout << "Date(int year, int month, int day)" << endl;
	}
	//拷貝構(gòu)造
	Date(const Date& d)
		:_year(d._year)
		, _month(d._month)
		, _day(d._day)
	{
		cout << "Date(const Date& d)" << endl;
	}
private:
	int _year = 1;
	int _month = 1;
	int _day = 1;
};

同樣尾插:

int main()
{
	std::list<Date> lt1;
	lt1.push_back({ 2024,3,30 });
	cout << "=============================================" << endl;
	lt1.emplace_back(2024, 3, 30);
	return 0;
}

【C++】C++11可變參數(shù)模板,C++,c++,開(kāi)發(fā)語(yǔ)言

注意:push_back支持initializer_list作為參數(shù)是因?yàn)閜ush_back的參數(shù)就是模板類(lèi)型,所以他知道插入的對(duì)象是Date類(lèi)型,就直接走多參數(shù)的隱式類(lèi)型轉(zhuǎn)換構(gòu)造一個(gè)Date對(duì)象了,而emplace不支持initializer_list作為構(gòu)造參數(shù),因?yàn)閑mplace需要可變參數(shù)模板去底層構(gòu)造list節(jié)點(diǎn),你放到initializer_list中就相當(dāng)于把參數(shù)又封裝起來(lái)了:

int main()
{
	std::list<Date> lt1;
	lt1.push_back({ 2024,3,30 });

	// 不支持
	//lt1.emplace_back({ 2024,3,30 });

	// 正確寫(xiě)法
	lt1.emplace_back(2024, 3, 30);

	return 0;
}

如果給emplace的參數(shù)是現(xiàn)成的對(duì)象(不管有名對(duì)象還是匿名對(duì)象),那emplace就沒(méi)有任何優(yōu)勢(shì)了:

int main()
{
	std::list<Date> lt1;

	Date d1(2023, 1, 1);
	lt1.push_back(d1);
	lt1.emplace_back(d1);

	cout << "=============================================" << endl;

	lt1.push_back(Date(2023, 1, 1));
	lt1.emplace_back(Date(2023, 1, 1));
	return 0;
}

【C++】C++11可變參數(shù)模板,C++,c++,開(kāi)發(fā)語(yǔ)言


總結(jié)

  • emplace系列接口使用需要直接傳入?yún)?shù)包才能體現(xiàn)emplace接口的價(jià)值與意義,因?yàn)閑mplace系列接口真正高效的情況是傳入?yún)?shù)包的時(shí)候,直接通過(guò)參數(shù)包構(gòu)造出對(duì)象,避免了中途的一次拷貝。
  • 所以emplace系列接口并不是在所有場(chǎng)景下都比原有的插入接口高效,如果傳入的是對(duì)象(不管有名還是匿名),那么emplace系列接口的效率其實(shí)和原有的插入接口的效率是一樣的。
  • 以上兩條告訴我們:以后使用emplace就直接傳參數(shù)包,不要構(gòu)造了對(duì)象后再將該對(duì)象作為參數(shù)傳給emplace,直接傳參數(shù)包才是emplace存在的價(jià)值和意義。
  • 并且emplace系列接口對(duì)于深拷貝的且實(shí)現(xiàn)了移動(dòng)構(gòu)造的類(lèi)意義不大,因?yàn)橐苿?dòng)構(gòu)造的代價(jià)很小,emplace帶來(lái)的效率提升并不會(huì)很明顯,emplace系列接口對(duì)于淺拷貝的類(lèi)可以節(jié)省拷貝(拷貝代價(jià)高,并且淺拷貝的類(lèi)沒(méi)有移動(dòng)構(gòu)造),所以emplace對(duì)于淺拷貝的類(lèi)插入提升很明顯。

List類(lèi)增添模擬實(shí)現(xiàn)emplace系列函數(shù)

構(gòu)造

template<class ...Args>
ListNode(Args&&... args)
    : _next(nullptr)
    , _prev(nullptr)
    , _data(forward<Args>(args)...)
{}

emplace_back()

template<class ...Args>
void emplace_back(Args&&... args)
{
    emplace(end(), forward<Args>(args)...);
}

emplace()

template<class ...Args>
iterator emplace(iterator pos, Args&&... args)
{
    Node* cur = pos._node;
    Node* prev = cur->_prev;
    Node* newnode = new Node(forward<Args>(args)...);

    prev->_next = newnode;
    newnode->_prev = prev;
    newnode->_next = cur;
    cur->_prev = newnode;

    //return iterator(newnode);
    return newnode;
}

=========================================================================

如果你對(duì)該系列文章有興趣的話,歡迎持續(xù)關(guān)注博主動(dòng)態(tài),博主會(huì)持續(xù)輸出優(yōu)質(zhì)內(nèi)容

??博主很需要大家的支持,你的支持是我創(chuàng)作的不竭動(dòng)力??

??~ 點(diǎn)贊收藏+關(guān)注 ~??

=========================================================================

到了這里,關(guān)于【C++】C++11可變參數(shù)模板的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【C++11】移動(dòng)賦值 | 新的類(lèi)功能 | 可變參數(shù)模板

    【C++11】移動(dòng)賦值 | 新的類(lèi)功能 | 可變參數(shù)模板

    C++11中,string中的operator= 包含 參數(shù)為右值的版本 C++98中 沒(méi)有移動(dòng)賦值和移動(dòng)構(gòu)造 , 只有參數(shù)為左值 的賦值重載(operator=)和拷貝構(gòu)造 本來(lái)只有兩次深拷貝,但是由于調(diào)用拷貝賦值時(shí),內(nèi)部又進(jìn)行一次拷貝構(gòu)造,所以導(dǎo)致最終進(jìn)行三次深拷貝 這里編譯器是不能優(yōu)化的, 因?yàn)閮?yōu)

    2024年02月08日
    瀏覽(26)
  • C++11『右值引用 ‖ 完美轉(zhuǎn)發(fā) ‖ 新增類(lèi)功能 ‖ 可變參數(shù)模板』

    C++11『右值引用 ‖ 完美轉(zhuǎn)發(fā) ‖ 新增類(lèi)功能 ‖ 可變參數(shù)模板』

    ?個(gè)人主頁(yè): 北 海 ??所屬專欄: C++修行之路 ??操作環(huán)境: Visual Studio 2022 版本 17.6.5 自從C++98以來(lái),C++11無(wú)疑是一個(gè)相當(dāng)成功的版本更新。它引入了許多重要的語(yǔ)言特性和標(biāo)準(zhǔn)庫(kù)增強(qiáng),為C++編程帶來(lái)了重大的改進(jìn)和便利。C++11的發(fā)布標(biāo)志著C++語(yǔ)言的現(xiàn)代化和進(jìn)步,為程序員

    2024年02月05日
    瀏覽(25)
  • C++11可變參數(shù)模板(typename... Args模板參數(shù)包或class... Args)(Args... args函數(shù)參數(shù)包)(遞歸展開(kāi)與參數(shù)包展開(kāi)(只支持C++17))

    C++11可變參數(shù)模板(typename... Args模板參數(shù)包或class... Args)(Args... args函數(shù)參數(shù)包)(遞歸展開(kāi)與參數(shù)包展開(kāi)(只支持C++17))

    C++可變參數(shù)是指函數(shù)的參數(shù)個(gè)數(shù)是可變的,可以在函數(shù)定義時(shí)不確定參數(shù)的個(gè)數(shù),需要在函數(shù)體內(nèi)通過(guò)特定的語(yǔ)法來(lái)處理這些參數(shù)。C++11標(biāo)準(zhǔn)引入了新的可變參數(shù)模板,使得可變參數(shù)的處理更加方便和靈活。在函數(shù)定義時(shí),可以使用省略號(hào)(…)來(lái)表示可變參數(shù),然后通過(guò)va_li

    2024年02月08日
    瀏覽(20)
  • 【C++】C++11新特性重點(diǎn):可變參數(shù)+lambda

    【C++】C++11新特性重點(diǎn):可變參數(shù)+lambda

    C++11新特性第二篇重點(diǎn) 文章目錄 上一篇的補(bǔ)充 一、可變參數(shù)模板 二、lambda函數(shù) 總結(jié) 上一篇我們重點(diǎn)講解了右值引用+移動(dòng)語(yǔ)義,關(guān)于移動(dòng)構(gòu)造和移動(dòng)賦值還有一些需要補(bǔ)充的知識(shí): 如果你沒(méi)有自己實(shí)現(xiàn)移動(dòng)構(gòu)造函數(shù),且沒(méi)有實(shí)現(xiàn)析構(gòu)函數(shù) 、拷貝構(gòu)造、拷貝賦值重載中的任

    2024年02月09日
    瀏覽(28)
  • 【C++】C++11右值引用|新增默認(rèn)成員函數(shù)|可變參數(shù)模版|lambda表達(dá)式

    【C++】C++11右值引用|新增默認(rèn)成員函數(shù)|可變參數(shù)模版|lambda表達(dá)式

    在C++11之前,我們只有引用的概念,沒(méi)有接觸到所謂的左值引用或者是右值引用這種概念,從C++11開(kāi)始,增加了右值引用的概念,那么現(xiàn)在我們將對(duì)引用進(jìn)行一個(gè)概念上的區(qū)分。在此之前我們所說(shuō)的引用都是左值引用,對(duì)于左值引用相關(guān)的內(nèi)容,可以去看一看博主之前寫(xiě)的文章

    2024年02月15日
    瀏覽(34)
  • template<typename ... Args>:可變參數(shù)模板的解釋和使用
  • 【C】【C++】可變參數(shù)、不定參函數(shù)的使用

    【C】【C++】可變參數(shù)、不定參函數(shù)的使用

    C 語(yǔ)言中的可變參數(shù)寫(xiě)法: ... 1.1 可變宏函數(shù) 以日志舉例,我們寫(xiě)入日志時(shí)只需要輸入關(guān)鍵信息,行號(hào)文件等由宏函數(shù)補(bǔ)全 這其中,我們需要輸入的信息是格式不定的,需要用到可變參數(shù) 輸出結(jié)果: C語(yǔ)言庫(kù)中的宏 __FILE__ :字符串,記錄當(dāng)前文件名 __LINE__ :整型,記錄當(dāng)前

    2024年02月09日
    瀏覽(23)
  • C++模板的模板參數(shù)(五)

    在C++中,模板的模板參數(shù)(Template Template Parameters)是一種特殊的模板參數(shù),允許我們將另一個(gè)模板作為模板參數(shù)傳遞給一個(gè)模板。這種技術(shù)可以用于實(shí)現(xiàn)更靈活和通用的模板設(shè)計(jì)。 模板的模板參數(shù)使用兩個(gè) “template” 來(lái)指示,其中第一個(gè) “template” 用于聲明模板參數(shù)

    2024年02月10日
    瀏覽(19)
  • 【c++隨筆08】可變參數(shù)——va_list、va_start、va_end、va_arg

    原創(chuàng)作者:鄭同學(xué)的筆記 原創(chuàng)地址:https://zhengjunxue.blog.csdn.net/article/details/131690070 qq技術(shù)交流群:921273910 當(dāng)你在編寫(xiě) C++ 函數(shù)時(shí),有時(shí)候你會(huì)需要處理可變數(shù)量的參數(shù)。C++ 中提供了 頭文件,其中包含了用于處理可變參數(shù)的函數(shù)和宏。本教程將向你介紹如何使用 來(lái)編寫(xiě)可變參

    2024年02月07日
    瀏覽(19)
  • 【C++】模板進(jìn)階——非類(lèi)型模板參數(shù)、模板特化、模板分離編譯

    【C++】模板進(jìn)階——非類(lèi)型模板參數(shù)、模板特化、模板分離編譯

    模板參數(shù)分為類(lèi)型形參 與 非類(lèi)型形參 類(lèi)型形參 :出現(xiàn)在模板參數(shù)列表中,跟在class或者typedename之類(lèi)的參數(shù)類(lèi)型名稱。 非類(lèi)型形參 :用一個(gè)常量作為類(lèi)(函數(shù))模板的一個(gè)參數(shù),在類(lèi)(函數(shù))模板中可將該參數(shù)當(dāng)成常量來(lái)使用。 非類(lèi)型模板參數(shù)的優(yōu)勢(shì): 有些容器需要在創(chuàng)建對(duì)象

    2024年02月01日
    瀏覽(26)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包