c++ emplace_back

概述

為了在容器操作時(shí)盡可能的減少構(gòu)造函數(shù)的調(diào)用和內(nèi)存的拷貝,C++11 引入了emplace_back的方法乓序,該方法可以改善往容器內(nèi)推入元素對(duì)象時(shí)的效率丹鸿。相比push_back付鹿, push_front等成員函數(shù)蜜氨,它可以節(jié)省一次拷貝構(gòu)造函數(shù)的調(diào)用從而提高插入效率。

代碼演示

#include <iostream>
#include <string>
#include <vector>

struct President
{
    std::string name;
    std::string country;
    int year;

    President(std::string p_name, std::string p_country, int p_year)
        : name(std::move(p_name)), country(std::move(p_country)), year(p_year)
    {
        std::cout << "I am being constructed.\n";
    }
    President(const President& other)
        : name(std::move(other.name)), country(std::move(other.country)), year(other.year)
    {
        std::cout << "I am being copy constructed.\n";
    }
    President(President&& other)
        : name(std::move(other.name)), country(std::move(other.country)), year(other.year)
    {
        std::cout << "I am being moved.\n";
    }
    President& operator=(const President& other);
};

int main()
{
    std::vector<President> elections;
    std::cout << "emplace_back:\n";
    elections.emplace_back("Nelson Mandela", "South Africa", 1994); //沒有類的創(chuàng)建

    std::vector<President> reElections;
    std::cout << "\npush_back:\n";
    reElections.push_back(President("Franklin Delano Roosevelt", "the USA", 1936));

    std::cout << "\nContents:\n";
    for (President const& president: elections) {
       std::cout << president.name << " was elected president of "
            << president.country << " in " << president.year << ".\n";
    }
    for (President const& president: reElections) {
        std::cout << president.name << " was re-elected president of "
            << president.country << " in " << president.year << ".\n";
    }
}

執(zhí)行結(jié)果

g++ emplace_back_push_back.cc --std=c++11

guanyunfei@ivan:~/practice/c++$ ./a.out
emplace_back:
I am being constructed.

push_back:
I am being constructed.
I am being moved.

Contents:
Nelson Mandela was elected president of South Africa in 1994.
Franklin Delano Roosevelt was re-elected president of the USA in 1936.

結(jié)果分析

? 從結(jié)果看稠诲,確實(shí)在調(diào)用emplace_back成員函數(shù)的時(shí)候少了一次拷貝構(gòu)造函數(shù)或者移動(dòng)構(gòu)造函數(shù)侦鹏。但是細(xì)心的朋友可以發(fā)現(xiàn)诡曙,emplace_back()成員函數(shù)調(diào)用的時(shí)候我們是直接用類的參數(shù)列表作為形參的(push_back不能這么使用,它必須接收現(xiàn)成的對(duì)象或者對(duì)象在指針)略水,所以確實(shí)可以少一次拷貝構(gòu)造函數(shù)价卤。那么問題來了,如果我們要把一個(gè)已存在的對(duì)象推入容器時(shí)渊涝,會(huì)不會(huì)調(diào)用呢慎璧?

代碼展示

int main()
{
    std::vector<President> elections;
    std::cout << "emplace_back:\n";
    //elections.emplace_back("Nelson Mandela", "South Africa", 1994); //沒有類的創(chuàng)建
    //elections.emplace_back("Nelson Mandela", "South Africa", 1994); //沒有類的創(chuàng)建

    President Nelson("Nelson Mandela", "South Africa", 1994);
    elections.emplace_back(Nelson); //拷貝構(gòu)造函數(shù)

    std::cout << "\nemplace_back2:\n";
    elections.emplace_back(President("Joseph Robinette Biden", "US", 2021)); //構(gòu)造,移動(dòng)構(gòu)造跨释,拷貝構(gòu)造函數(shù)


    std::vector<President> reElections;
    std::cout << "\npush_back:\n";
    President Trump("Donald Trump", "US", 2016);
    reElections.push_back(Trump);

    std::cout << "\npush_back2:\n";
    reElections.push_back(President("Franklin Delano Roosevelt", "the USA", 1936));

    std::cout << "\nContents:\n";
    for (President const& president: elections) {
       std::cout << president.name << " was elected president of "
            << president.country << " in " << president.year << ".\n";
    }
    for (President const& president: reElections) {
        std::cout << president.name << " was re-elected president of "
            << president.country << " in " << president.year << ".\n";
    }
}

結(jié)果展示

emplace_back:
I am being constructed.
I am being copy constructed.

emplace_back2:
I am being constructed.
I am being moved.
I am being copy constructed.

push_back:
I am being constructed.
I am being copy constructed.

push_back2:
I am being constructed.
I am being moved.
I am being copy constructed.

Contents:
Nelson Mandela was elected president of South Africa in 1994.
Joseph Robinette Biden was elected president of US in 2021.
Donald Trump was re-elected president of US in 2016.
Franklin Delano Roosevelt was re-elected president of the USA in 1936.

結(jié)果分析

? 從結(jié)果可以看出當(dāng)我們推入一個(gè)已經(jīng)存在的對(duì)象時(shí)push_back()和emplace_back()的表現(xiàn)完全一樣都要去調(diào)用拷貝構(gòu)造函數(shù)炸卑。當(dāng)讓臨時(shí)對(duì)象作為形參推入容器時(shí)兩者表現(xiàn)也完全一樣,都要調(diào)用拷貝煤傍,移動(dòng),拷貝構(gòu)造函數(shù)嘱蛋。

總結(jié)

? emplace_back()之所以可能提高效率時(shí)因?yàn)槠涮峁┝丝梢灾苯虞斎腩悈?shù)列表的功能蚯姆,可以直接在容器內(nèi)部新建這個(gè)對(duì)象。而push_back(),push_front()等函數(shù)不具備這個(gè)凡爾賽功能洒敏。

? 當(dāng)然如果我們想提高效率時(shí)龄恋,也可以讓容器變?yōu)橹羔樔萜鳎綍r(shí)候直接推入指針變量即可凶伙。這樣的話郭毕,每次推入的代價(jià)就由真?zhèn)€類的的拷貝構(gòu)造函數(shù)轉(zhuǎn)為了指針的拷貝,效率會(huì)明顯提升函荣。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末显押,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子傻挂,更是在濱河造成了極大的恐慌乘碑,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件金拒,死亡現(xiàn)場離奇詭異兽肤,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)绪抛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門资铡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人幢码,你說我怎么就攤上這事笤休。” “怎么了蛤育?”我有些...
    開封第一講書人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵宛官,是天一觀的道長葫松。 經(jīng)常有香客問我,道長底洗,這世上最難降的妖魔是什么腋么? 我笑而不...
    開封第一講書人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮亥揖,結(jié)果婚禮上珊擂,老公的妹妹穿的比我還像新娘。我一直安慰自己费变,他們只是感情好摧扇,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著挚歧,像睡著了一般扛稽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上滑负,一...
    開封第一講書人閱讀 49,749評(píng)論 1 289
  • 那天在张,我揣著相機(jī)與錄音,去河邊找鬼矮慕。 笑死帮匾,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的痴鳄。 我是一名探鬼主播瘟斜,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼痪寻!你這毒婦竟也來了螺句?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤槽华,失蹤者是張志新(化名)和其女友劉穎壹蔓,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體猫态,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡佣蓉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了亲雪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片勇凭。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖义辕,靈堂內(nèi)的尸體忽然破棺而出虾标,到底是詐尸還是另有隱情,我是刑警寧澤灌砖,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布璧函,位于F島的核電站傀蚌,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏蘸吓。R本人自食惡果不足惜善炫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望库继。 院中可真熱鬧箩艺,春花似錦、人聲如沸宪萄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽拜英。三九已至静汤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間居凶,已是汗流浹背撒妈。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留排监,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓杰捂,卻偏偏與公主長得像舆床,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子嫁佳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容