typedef map<KeyType, ValType> KVMap;
KVMap kvmap;
kvmap.insert( KVMap::value_type( key, val ) );
kvmap.insert( make_pair( key, val ) );
要插入STL地图的上述哪个选项总是更快?为什么呢?
注意:我很清楚insert()
比使用[]=
向地图添加(不更新)键值对更快。请假设我的查询是关于添加,而不是更新。因此我将其限制为insert()
。
答案 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
很可能会将其模板参数推断为KeyType
和ValType
,从而返回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
),
并且一次复制 - 构建地图的内部节点。
因此,如果您将insert
与make_pair
一起使用,
不能说即使添加insert
总是比operator[]
更快。
可能,这取决于具体情况。
如您所知,鉴于上述情况,emplace
被提议用于新的
标准。
答案 3 :(得分:2)
它们基本上是一回事。 KVMap::value_type
是std::pair<KeyType, ValType>
的typedef,因此只是调用构造函数。 std::make_pair
是一个简单地调用构造函数的模板函数(它存在,因为模板类型可以推导出自由函数,但不能用于构造函数)。一旦完成所有令人难以置信的标准优化,就没有理由存在任何差异。
我不知道你是如何测试的,但有很多方法可以做错。
至于insert()
与通过operator[]
分配,后者必须在概念上做更多的工作(当你以这种方式添加新元素时,它首先应该默认构造一个元素,并且然后根据ValType
进行分配,但可以想象它可以再次优化为基本相同的东西。