简体   繁体   English

C ++:value_type与make_pair,对于地图插入更快?

[英]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 ) );

Which of the above options to insert to a STL map is always faster? 要插入STL地图的上述哪个选项总是更快? Why? 为什么?

Note: I am well aware that insert() is faster than using []= for adding (not updating) key-value pairs to a map. 注意:我很清楚insert()比使用[]=向键添加(不更新)键值对更快。 Please assume that my query is about adding, not updating. 请假设我的查询是关于添加,而不是更新。 Hence I have restricted it to insert() . 因此我将其限制为insert()

Chances are that the first will be 'epsilon-faster' , because of this (from 23.3.1 in the standard) : 有可能第一个将是'epsilon-faster' ,因为这个(从标准中的23.3.1):

typedef pair<const Key, T> value_type;

[...]

pair<iterator, bool> insert(const value_type& x);
  • In the first version, you directly construct the appropriate type expected by std::map<K,V>::insert 在第一个版本中,您直接构造std::map<K,V>::insert期望的适当类型

  • In the second version, a conversion using std::pair template constructor is involved. 在第二个版本中,涉及使用std::pair模板构造函数的转换。 Indeed, std::make_pair will most likely deduce its template arguments to KeyType and ValType , thus returning a std::pair<KeyType, ValType> . 实际上, std::make_pair很可能会将其模板参数推断为KeyTypeValType ,从而返回std::pair<KeyType, ValType>

    This does not match the parameter type of std::map<K,V>::insert , which is std::pair<const KeyType, ValType> (the difference being the const -qualified first). 这与std::map<K,V>::insert的参数类型不匹配,它是std::pair<const KeyType, ValType> (差异是const限定的第一个)。 The std::pair conversion constructor will be used to create a std::pair<const K, V> from the std::pair<K, V> . std::pair转换构造函数将用于从std::pair<K, V>创建std::pair<const K, V> std::pair<K, V>

To be fair, I don't believe you could even measure the difference (and I'm not even sure that popular compilers will actually generate a different code for these). 公平地说,我不相信你甚至可以衡量差异(我甚至不确定流行的编译器实际上会为这些编译生成不同的代码)。

There actually is an argument to be made for value_type over make_pair . 实际上有一个关于make_pair value_type的参数。 This is because, for various arcane reasons, make_pair accepts its arguments by value. 这是因为,出于各种神秘的原因, make_pair按值接受其参数。 On the other hand, value_type , an alias for std::pair<const Key, value> , will have its constructor called with the arguments passed by const reference. 另一方面, value_typestd::pair<const Key, value>的别名,将使用const引用传递的参数调用其构造函数。 There's a potential loss of efficiency from the pass-by-value in make_pair versus pass-by-reference, which could in theory have a noticeable impact on your program. make_pair的pass-by-value与pass-by-reference可能会导致效率下降,理论上这可能对您的程序产生显着影响。

Another issue to be worried about with make_pair is that make_pair will usually create a pair of type std::pair<Key, Value> versus the std::pair<const Key, Value> needed inside the map . make_pair要担心的另一个问题是make_pair通常会创建一对std::pair<Key, Value>类型std::pair<Key, Value>而不是map所需的std::pair<const Key, Value> This means that there might be another unnecessary copy being made, this time of the pair to get the conversion working correctly. 这意味着可能会有另一个不必要的副本,这一pair时间可以使转换正常工作。

In short, using make_pair might cause two completely unnecessary copies of the key and value to get made, while using the value_type constructor has none. 简而言之,使用make_pair可能会导致两个完全不必要的键和值副本,而使用value_type构造函数则没有。

This is just a supplementation. 这只是补充。

insert( make_pair(...) ) calls copy constructor 4 times notionally because of the reason other answerers mentioned. insert( make_pair(...) )由于其他回答者提到的原因,在概念上调用了4次复制构造函数。

insert( value_type(...) ) calls copy constructor 2 times. insert( value_type(...) )调用复制构造函数2次。

operator[] calls default constructor once and copy constructor 2 times in a typical implementation. operator[]调用默认构造函数一次,并在典型实现中复制构造函数2次。 default constructor is called inside operator[] for insert( value_type( ..., mapped_type() ) ) . 默认构造函数在operator[]内调用insert( value_type( ..., mapped_type() ) ) copy constructor is called once for copying insert() 's argument( pair ), and once to copy-construct an internal node of the map. 复制构造函数被调用一次用于复制insert()的参数( pair ),并且一次被复制构造一个内部节点的地图。

So, if you use insert with make_pair , it cannot be said that insert is always faster than operator[] even for adding. 因此,如果你使用带有make_pair insert ,那么即使添加,也不能说insert总是比operator[]快。 Probably, it depends on the situation. 可能,这取决于具体情况。 As you may know, in view of the above, emplace was proposed for the new standard. 正如你可能知道,鉴于上述情况, emplace提出了新的标准。

They are fundamentally the same thing. 它们基本上是一回事。 KVMap::value_type is a typedef for std::pair<KeyType, ValType> , so that's just calling the constructor. KVMap::value_typestd::pair<KeyType, ValType>的typedef,所以它只是调用构造函数。 std::make_pair is a template function that simply calls the constructor (it exists because template types can be deduced for free functions, but not for constructors). std::make_pair是一个简单地调用构造函数的模板函数(它存在,因为模板类型可以推导出自由函数,但不能用于构造函数)。 Once all the unbelievably-standard optimizations are done, there is no reason for there to be any difference. 一旦完成所有令人难以置信的标准优化,就没有理由存在任何差异。

I don't know how you're testing, but there are many, many ways to do that wrong. 我不知道你是如何测试的,但是有很多方法可以做错。

As for insert() vs. assigning via operator[] , the latter has to do more work conceptually (when you add a new element this way, it first is supposed to default-construct an element, and then assign over top of it), but depending on the ValType , it could conceivably be optimized into basically the same thing again. 至于insert()与通过operator[]分配,后者必须在概念上做更多的工作(当你以这种方式添加一个新元素时,它首先应该默认构造一个元素,然后在它上面分配) ,但根据ValType ,可以想象它可以再次优化为基本相同的东西。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM