C++:value_type 与 make_pair,哪个映射插入更快?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4623610/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 15:58:23  来源:igfitidea点击:

C++: value_type versus make_pair, which is faster for map insert?

c++mapinsert

提问by Ashwin Nanjappa

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? Why?

插入到 STL 映射的上述哪个选项总是更快?为什么?

Note: I am well aware that insert()is faster than using []=for adding (not updating) key-value pairs to a map. Please assume that my query is about adding, not updating. Hence I have restricted it to insert().

注意:我很清楚这insert()[]=用于向地图添加(不更新)键值对要快。请假设我的查询是关于添加,而不是更新。因此,我将其限制为insert().

采纳答案by icecrime

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

  • In the second version, a conversion using std::pairtemplate constructor is involved. Indeed, std::make_pairwill most likely deduce its template arguments to KeyTypeand ValType, thus returning a 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). The std::pairconversion constructor will be used to create a std::pair<const K, V>from the std::pair<K, V>.

  • 在第一个版本中,您直接构造了预期的适当类型 std::map<K,V>::insert

  • 在第二个版本中,std::pair涉及使用模板构造函数的转换。实际上,std::make_pair很可能会将其模板参数推导出为KeyTypeand ValType,从而返回 a std::pair<KeyType, ValType>

    这与 的参数类型不匹配std::map<K,V>::insert,即std::pair<const KeyType, ValType>(区别在于const- 限定在前)。该std::pair转换构造函数将被用来建立一个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).

公平地说,我不相信你甚至可以衡量差异(我什至不确定流行的编译器实际上会为这些生成不同的代码)。

回答by templatetypedef

There actually is an argument to be made for value_typeover make_pair. This is because, for various arcane reasons, make_pairaccepts its arguments by value. 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. There's a potential loss of efficiency from the pass-by-value in make_pairversus pass-by-reference, which could in theory have a noticeable impact on your program.

实际上有一个争论要value_type结束make_pair。这是因为,出于各种神秘的原因,make_pair按值接受其参数。另一方面,value_type, 的别名std::pair<const Key, value>, 将使用由 const 引用传递的参数调用其构造函数。make_pair与通过引用传递值相比,传递值存在潜在的效率损失,理论上这可能会对您的程序产生显着影响。

Another issue to be worried about with make_pairis that make_pairwill usually create a pair of type std::pair<Key, Value>versus the std::pair<const Key, Value>needed inside the map. This means that there might be another unnecessary copy being made, this time of the pairto get the conversion working correctly.

与担心的另一个问题make_pair是,make_pair通常会创建一个对类型std::pair<Key, Value>相对于std::pair<const Key, Value>需要内部map。这意味着可能会制作另一个不必要的副本,这次是pair为了使转换正常工作。

In short, using make_pairmight cause two completely unnecessary copies of the key and value to get made, while using the value_typeconstructor has none.

简而言之,使用make_pair可能会导致生成两个完全不必要的键和值副本,而使用value_type构造函数则没有。

回答by Ise Wisteria

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. default constructor is called inside operator[]for 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.

operator[]在典型的实现中调用一次默认构造函数并复制构造函数 2 次。在operator[]for 内部调用默认构造函数insert( value_type( ..., mapped_type() ) )。复制构造函数被调用一次以复制insert()的参数(pair),一次复制构造映射的内部节点。

So, if you use insertwith make_pair, it cannot be said that insertis always faster than operator[]even for adding. Probably, it depends on the situation. As you may know, in view of the above, emplacewas proposed for the new standard.

所以,如果你使用insertwith make_pair,不能说它insert总是比operator[]添加更快。也许,这取决于情况。如您所知,鉴于上述情况,emplace提出了新标准。

回答by Karl Knechtel

They are fundamentally the same thing. KVMap::value_typeis a typedef for std::pair<KeyType, ValType>, so that's just calling the constructor. std::make_pairis a template function that simply calls the constructor (it exists because template types can be deduced for free functions, but not for constructors). Once all the unbelievably-standard optimizations are done, there is no reason for there to be any difference.

它们基本上是同一回事。KVMap::value_type是一个 typedef for std::pair<KeyType, ValType>,所以这只是调用构造函数。std::make_pair是一个简单调用构造函数的模板函数(它存在是因为可以为自由函数推导出模板类型,但不能为构造函数推导出模板类型)。一旦完成了所有令人难以置信的标准优化,就没有理由存在任何差异。

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()与分配 via operator[],后者必须在概念上做更多的工作(当你以这种方式添加一个新元素时,它首先应该默认构造一个元素,然后在它上面分配),但取决于ValType,可以想象,它可以再次优化为基本相同的东西。