emplace_back減少內存拷貝和移動


--------《深入應用C++11:代碼優化與工程級應用》第2章使用C++11改進程序性能,本章將分別介紹右值引用相關的新特性。本節為大家介紹emplace_back減少內存拷貝和移動。---------

2.4 emplace_back減少內存拷貝和移動

emplace_back能就地通過參數構造對象,不需要拷貝或者移動內存,相比push_back能更好地避免內存的拷貝與移動,使容器插入元素的性能得到進一步提升。在大多數情況下應該優先使用emplace_back來代替push_back。所有的標准庫容器(array除外,因為它的長度不可改變,不能插入元素)都增加了類似的方法:emplace、emplace_hint、emplace_front、emplace_after和 emplace_back,關於它們的具體用法可以參考cppreference.com。這里僅列舉典型的示例。

vector的emplace_back的基本用法如下:
 

可以看出,emplace_back的用法比較簡單,直接通過構造函數的參數就可以構造對象,因此,也要求對象有對應的構造函數,如果沒有對應的構造函數,編譯器會報錯。如果把上面的構造函數注釋掉,在vs2013下編譯會報如下錯誤:
 error C2661: “A::A”: 沒有重載函數接受 2 個參數 

其他容器相應的emplace方法也是類似的。

相對push_back而言,emplace_back更具性能優勢。下面通過一個例子來看emplace_back和push_back的性能差異,如代碼清單2-5所示。

代碼清單2-5 emplace_back和push_back的比較

#include <vector> 
#include <map> 
#include <string> 
#include <iostream> 
using namespace std;  
 
struct Complicated  
{  
         int year;  
         double country;  
         std::string name;  
 
         Complicated(int a, double b, string c):year(a),country(b),name(c)  
         {  
                  cout<<"is constucted"<<endl;  
         }  
 
         Complicated(const Complicated&other):year(other.year),country(other.country),name(std::move(other.name))  
         {  
                  cout<<"is moved"<<endl;  
         }  
};  
 
int main()  
{  
         std::map<int, Complicated> m;  
         int anInt = 4;  
         double aDouble = 5.0;  
         std::string aString = "C++";  
         cout<<"—insert--"<<endl;  
         m.insert(std::make_pair(4, Complicated(anInt, aDouble, aString)));  
 
         cout<<"—emplace--"<<endl;  
         // should be easier for the optimizer  
         m.emplace(4, Complicated(anInt, aDouble, aString));  
 
         cout<<"--emplace_back--"<<endl;  
         vector<Complicated> v;  
         v.emplace_back(anInt, aDouble, aString);  
         cout<<"--push_back--"<<endl;  
         v.push_back(Complicated(anInt, aDouble, aString));  
} 

輸出如下:
 

代碼清單2-5測試了map的emplace和vector的emplace_back,用map的insert方法插入元素時有兩次內存移動,而用emplace時只有一次內存移動;用vector的push_back插入元素時有兩次移動內存,而用emplace_back時沒有內存移動,是直接構造的。

可以看到,emplace/emplace_back的性能比之前的insert和push_back的性能要提高很多,我們應該盡量用emplace/emplace_back來代替原來的插入元素的接口以提高性能。需要注意的是,我們還不能完全用emplace_back來取代push_back等老接口,因為在某些場景下並不能直接使用emplace來進行就地構造,比如,當結構體中沒有提供相應的構造函數時就不能用emplace了,這時就只能用push_back。

 

另外可參考:STL vector中的emplace_back方法


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM