【C++11新特性】emplace與insert

C++11中大部分的容器對于添加元素除了傳統(tǒng)的 insert 或者 pusb_back/push_front 之外都提供一個新的函數(shù)叫做 emplace。 比如如果你想要向 vector 的末尾添加一個數(shù)據(jù)

nums.push_back(1);
nums.empace_back(1);

臨時變量

emplace 相較于insert最大的作用是避免產(chǎn)生不必要的臨時變量。舉例說明:

/// 定義結(jié)構(gòu)體可以使用大括號法構(gòu)造對象
struct Obj{
    Obj(int a, int b);
};

vector<Obj> v;
v.emplace(Obj.begin(), 0,0);      /// 沒有臨時變量產(chǎn)生
v.insert(Obj.begin(), obj(0, 0)); /// 需要產(chǎn)生一個臨時變量
v.insert(Obj.begin(), {0, 0});    /// 需要產(chǎn)生一個臨時變量

emplace 的語法看起來比較特別贝攒,后面兩個參數(shù)自動用來構(gòu)造 vector 內(nèi)部的 Obj對象誓禁。這是因為其內(nèi)部利用了 C++11 的兩個新特性 變參模板完美轉(zhuǎn)發(fā)井佑。

  • 變參模板: 函數(shù)可以接受任意參數(shù)绰播,適用于任意對象的構(gòu)建仗颈。
  • 完美轉(zhuǎn)發(fā): 使得接收下來的參數(shù)能夠原樣完美地傳遞給對象的構(gòu)造函數(shù)黍瞧,這帶來另一個方便性就是即使是構(gòu)造函數(shù)聲明為 explicit 它還是可以正常工作诸尽,因為它不存在臨時變量和隱式轉(zhuǎn)換。

性能區(qū)別

  • insert印颤、push_back之所以慢的原因在與創(chuàng)建臨時對象時,需要申請內(nèi)存空間, 申請內(nèi)存空間一向是耗時很嚴重的操作;之后再通過拷貝構(gòu)造函數(shù)把創(chuàng)建的臨時對象復制到vector空間中您机,期間的復制操作也是需要CPU時間的;
  • emplace_back之所以快的其原因是直接在vector中已有的空間上, 調(diào)用了構(gòu)造函數(shù), 節(jié)省了臨時對象的內(nèi)存空間申請以及移動構(gòu)造函數(shù)的復制操作.

emplace實現(xiàn)原理

  • push_back先向容器尾部添加一個右值元素(臨時對象),然后調(diào)用構(gòu)造函數(shù)構(gòu)造出這個臨時對象年局,最后調(diào)用移動構(gòu)造函數(shù)將這個臨時對象放入容器中并釋放這個臨時對象际看。
    注:最后調(diào)用的不是拷貝構(gòu)造函數(shù),而是移動構(gòu)造函數(shù)矢否。因為需要釋放臨時對象仲闽,所以通過std::move進行移動構(gòu)造,可以避免不必要的拷貝操作
  • emplace_back在容器尾部添加一個元素僵朗,調(diào)用構(gòu)造函數(shù)原地構(gòu)造赖欣,不需要觸發(fā)拷貝構(gòu)造和移動構(gòu)造屑彻。因此更加高效。

三種構(gòu)造函數(shù)的聲明方式:

/// 構(gòu)造函數(shù)
Student(Student&& s) : name(std::move(s.name)), age(s.age);
/// 拷貝構(gòu)造
Student(const Student& s) : name(std::move(s.name)), age(s.age);
/// 移動構(gòu)造函數(shù)
Student(string&& n, int a) : name(std::move(n)), age(a);

emplace_back函數(shù)顶吮,它通過完美轉(zhuǎn)發(fā)實現(xiàn)了在vector中插入時直接在容器內(nèi)構(gòu)造對象社牲,省略了創(chuàng)建臨時對象的操作。我們看下它的代碼就不難理解.

template<class _Ty,
    class _Alloc = allocator<_Ty>>
    class vector
        : public _Vector_alloc<_Vec_base_types<_Ty, _Alloc>>
{
...
public:
  template<class... _Valty>
  decltype(auto) emplace_back(_Valty&&... _Val)
  { // insert by perfectly forwarding into element at end, provide strong guarantee
        if (_Has_unused_capacity())
    {
       return (_Emplace_back_with_unused_capacity(_STD forward<_Valty>(_Val)...));
    }

    _Ty& _Result = *_Emplace_reallocate(this->_Mylast(), _STD forward<_Valty>(_Val)...);

    return (_Result);
  }
...
};

對于上面案例中的vector<string>來說悴了,_Ty是string搏恤,調(diào)用vector.emplace_back("6666"),則_Valty就是const char*让禀,通過完美轉(zhuǎn)發(fā)機制(forward<_Valty>)最終將傳入的參數(shù)_Val(本例中就是"6666")傳入string的構(gòu)造函數(shù)中挑社,實現(xiàn)了直接從list中一步到位構(gòu)造對象,省略了創(chuàng)建臨時對象的過程巡揍,從而減少了創(chuàng)建的時間痛阻。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市腮敌,隨后出現(xiàn)的幾起案子阱当,更是在濱河造成了極大的恐慌,老刑警劉巖糜工,帶你破解...
    沈念sama閱讀 211,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件弊添,死亡現(xiàn)場離奇詭異,居然都是意外死亡捌木,警方通過查閱死者的電腦和手機油坝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來刨裆,“玉大人澈圈,你說我怎么就攤上這事》校” “怎么了瞬女?”我有些...
    開封第一講書人閱讀 157,435評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長努潘。 經(jīng)常有香客問我诽偷,道長,這世上最難降的妖魔是什么疯坤? 我笑而不...
    開封第一講書人閱讀 56,509評論 1 284
  • 正文 為了忘掉前任报慕,我火速辦了婚禮,結(jié)果婚禮上贴膘,老公的妹妹穿的比我還像新娘卖子。我一直安慰自己,他們只是感情好刑峡,可當我...
    茶點故事閱讀 65,611評論 6 386
  • 文/花漫 我一把揭開白布洋闽。 她就那樣靜靜地躺著玄柠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪诫舅。 梳的紋絲不亂的頭發(fā)上羽利,一...
    開封第一講書人閱讀 49,837評論 1 290
  • 那天,我揣著相機與錄音刊懈,去河邊找鬼这弧。 笑死,一個胖子當著我的面吹牛虚汛,可吹牛的內(nèi)容都是我干的匾浪。 我是一名探鬼主播,決...
    沈念sama閱讀 38,987評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼卷哩,長吁一口氣:“原來是場噩夢啊……” “哼蛋辈!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起将谊,我...
    開封第一講書人閱讀 37,730評論 0 267
  • 序言:老撾萬榮一對情侶失蹤冷溶,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后尊浓,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體逞频,經(jīng)...
    沈念sama閱讀 44,194評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,525評論 2 327
  • 正文 我和宋清朗相戀三年栋齿,在試婚紗的時候發(fā)現(xiàn)自己被綠了苗胀。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,664評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡瓦堵,死狀恐怖柒巫,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情谷丸,我是刑警寧澤,帶...
    沈念sama閱讀 34,334評論 4 330
  • 正文 年R本政府宣布应结,位于F島的核電站刨疼,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏鹅龄。R本人自食惡果不足惜揩慕,卻給世界環(huán)境...
    茶點故事閱讀 39,944評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望扮休。 院中可真熱鬧迎卤,春花似錦、人聲如沸玷坠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,764評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至樟凄,卻和暖如春聘芜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背缝龄。 一陣腳步聲響...
    開封第一講書人閱讀 31,997評論 1 266
  • 我被黑心中介騙來泰國打工汰现, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人叔壤。 一個月前我還...
    沈念sama閱讀 46,389評論 2 360
  • 正文 我出身青樓瞎饲,卻偏偏與公主長得像,于是被迫代替她去往敵國和親炼绘。 傳聞我的和親對象是個殘疾皇子嗅战,可洞房花燭夜當晚...
    茶點故事閱讀 43,554評論 2 349

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