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

时间:2011-01-07 08:00:57

标签: c++ 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()

4 个答案:

答案 0 :(得分:20)

有可能第一个将是'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很可能会将其模板参数推断为KeyTypeValType,从而返回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>

公平地说,我认为你甚至无法衡量差异(我甚至不确定流行的编译器是否会为这些编译器生成不同的代码)。

答案 1 :(得分:12)

实际上有value_type超过make_pair的论点。这是因为,出于各种神秘的原因,make_pair按价值接受其论点。另一方面,value_type的别名std::pair<const Key, value>将使用const引用传递的参数调用其构造函数。 make_pair中的传递值与传递参考值相比可能会导致效率下降,理论上这可能会对您的计划产生明显的影响。

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

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

答案 2 :(得分:4)

这只是一种补充。

insert( make_pair(...) ) 由于其他原因,在名义上调用复制构造函数4次 回答者提到了。

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

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

因此,如果您将insertmake_pair一起使用, 不能说即使添加insert总是比operator[]更快。 可能,这取决于具体情况。 如您所知,鉴于上述情况,emplace被提议用于新的 标准。

答案 3 :(得分:2)

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

我不知道你是如何测试的,但有很多方法可以做错。

至于insert()与通过operator[]分配,后者必须在概念上做更多的工作(当你以这种方式添加新元素时,它首先应该默认构造一个元素,并且然后根据ValType进行分配,但可以想象它可以再次优化为基本相同的东西。