2011-01-29 64 views
11

按照documentation它:boost :: unordered_map.emplace(Args && ... args)如何工作?

插入的一個對象, 參數ARGS構造,在容器 當且僅當存在 用等效密鑰容器中沒有元件。

但是其可以被插入到一個unordered_map的唯一對象具有類型std::pair<Key const, Mapped>(因爲需要的對象既一個鍵和一個值被插入),這是已知的採取與正好兩個參數的構造函數。那麼爲什麼它使用可變參數函數形式呢?當然,我對此完全不瞭解。

回答

8

請參閱this關於emplace_back與push_back的SO文章。實質上,它允許從傳入的參數構造對象,而不需要先創建要傳入的對象。它通過刪除通常作爲創建要插入對象的結果而發生的複製構造來節省開銷。

所以,你可以逃脫這樣的:

unordered_map<int,int> foo; 
foo.emplace(4, 5); 

,而不是

foo.insert(std::make_pair(4, 5)); 

更妙的是,(如果我沒有記錯),你可以通過這條路線:

struct Bar{ 
    int x,y; 
    Bar(int _x, int _y) : x(_x), y(_y){} 
}; 

unordered_map<int,Bar> baz; 
baz.emplace(4, 5, 6); 

取自維基關於C++0x

由於右值引用的措辭的性質以及對左值引用(常規引用)的措辭的一些修改,右值引用允許開發人員提供完美的函數轉發。當與可變參數模板結合使用時,該功能允許功能模板將參數完美地轉發給接受這些特定參數的另一個函數。這對轉發構造函數參數非常有用,可以創建工廠函數,這些工廠函數將自動爲這些特定參數調用正確的構造函數。

以下方式其中一期工程:

template<typename TypeToConstruct> struct SharedPtrAllocator { 

    template<typename ...Args> std::shared_ptr<TypeToConstruct> construct_with_shared_ptr(Args&&... params) { 
     return std::shared_ptr<TypeToConstruct>(new TypeToConstruct(std::forward<Args>(params)...)); 
    } 
} 

再次,無恥地從上面提到的維基文章被盜。

+0

後面的例子對我來說似乎很陌生。假設我們有2個構造函數用於`Key`:`Key(int)`和`Key(int,int)`和2用於`Value`:`Value(int,int)`和`Value(int)`,編譯器會在構建「Key/Value」對時消除歧義? – 2011-01-29 18:35:58

5

現在的C++標準庫集成了升壓的那部分:

http://en.cppreference.com

#include <iostream> 
#include <utility> 
#include <tuple> 

#include <unordered_map> 

int main(){ 
    std::unordered_map<std::string, std::string> m; 

    // uses pair's piecewise constructor 
    m.emplace(std::piecewise_construct, 
     std::forward_as_tuple("c"), 
     std::forward_as_tuple(10, 'c')); 

    for (const auto &p : m) { 
     std::cout << p.first << " => " << p.second << '\n'; 
    } 
} 

std::piecewise_construct是不會留下任何有關的爭論將如何使用

歧義的常數
  • 第一個元組將被用於精讀結構鍵
  • 第二個構造值