[英]C++: value_type versus make_pair, which is faster for map insert?
typedef map<KeyType, ValType> KVMap;
KVMap kvmap;
kvmap.insert( KVMap::value_type( key, val ) );
kvmap.insert( make_pair( key, val ) );
要插入STL地圖的上述哪個選項總是更快? 為什么?
注意:我很清楚insert()
比使用[]=
向鍵添加(不更新)鍵值對更快。 請假設我的查詢是關於添加,而不是更新。 因此我將其限制為insert()
。
有可能第一個將是'epsilon-faster' ,因為這個(從標准中的23.3.1):
typedef pair<const Key, T> value_type;
[...]
pair<iterator, bool> insert(const value_type& x);
在第一個版本中,您直接構造std::map<K,V>::insert
期望的適當類型
在第二個版本中,涉及使用std::pair
模板構造函數的轉換。 實際上, std::make_pair
很可能會將其模板參數推斷為KeyType
和ValType
,從而返回std::pair<KeyType, ValType>
。
這與std::map<K,V>::insert
的參數類型不匹配,它是std::pair<const KeyType, ValType>
(差異是const
限定的第一個)。 std::pair
轉換構造函數將用於從std::pair<K, V>
創建std::pair<const K, V>
std::pair<K, V>
。
公平地說,我不相信你甚至可以衡量差異(我甚至不確定流行的編譯器實際上會為這些編譯生成不同的代碼)。
實際上有一個關於make_pair
value_type
的參數。 這是因為,出於各種神秘的原因, make_pair
按值接受其參數。 另一方面, value_type
是std::pair<const Key, value>
的別名,將使用const引用傳遞的參數調用其構造函數。 make_pair
的pass-by-value與pass-by-reference可能會導致效率下降,理論上這可能對您的程序產生顯着影響。
make_pair
要擔心的另一個問題是make_pair
通常會創建一對std::pair<Key, Value>
類型std::pair<Key, Value>
而不是map
所需的std::pair<const Key, Value>
。 這意味着可能會有另一個不必要的副本,這一pair
時間可以使轉換正常工作。
簡而言之,使用make_pair
可能會導致兩個完全不必要的鍵和值副本,而使用value_type
構造函數則沒有。
這只是補充。
insert( make_pair(...) )
由於其他回答者提到的原因,在概念上調用了4次復制構造函數。
insert( value_type(...) )
調用復制構造函數2次。
operator[]
調用默認構造函數一次,並在典型實現中復制構造函數2次。 默認構造函數在operator[]
內調用insert( value_type( ..., mapped_type() ) )
。 復制構造函數被調用一次用於復制insert()
的參數( pair
),並且一次被復制構造一個內部節點的地圖。
因此,如果你使用帶有make_pair
insert
,那么即使添加,也不能說insert
總是比operator[]
快。 可能,這取決於具體情況。 正如你可能知道,鑒於上述情況, emplace
提出了新的標准。
它們基本上是一回事。 KVMap::value_type
是std::pair<KeyType, ValType>
的typedef,所以它只是調用構造函數。 std::make_pair
是一個簡單地調用構造函數的模板函數(它存在,因為模板類型可以推導出自由函數,但不能用於構造函數)。 一旦完成所有令人難以置信的標准優化,就沒有理由存在任何差異。
我不知道你是如何測試的,但是有很多方法可以做錯。
至於insert()
與通過operator[]
分配,后者必須在概念上做更多的工作(當你以這種方式添加一個新元素時,它首先應該默認構造一個元素,然后在它上面分配) ,但根據ValType
,可以想象它可以再次優化為基本相同的東西。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.