std :: unordered_map :: insert的重载

时间:2013-02-06 04:11:53

标签: c++ c++11

你会教我两个原因吗

std::unordered_map::insert(const value_type&)

template<class P> std::unordered_map::insert(P&&)

存在于标准中吗?

我认为insert(P&&)可以作为insert(const value_type&)

3 个答案:

答案 0 :(得分:7)

这两个重载

auto std::unordered_map::insert(const value_type&) -> ...

template<class P>
auto std::unordered_map::insert(P&&) -> ...

有自己的优势,也不能完全取代对方。第一个似乎就像第二个的特殊情况,因为P可能被推断为const value_type&。关于第二次重载的好处是你可以避免不必要的副本。例如,在这种情况下:

mymap.insert(make_pair(7,"seven"));

此处,make_pair的结果实际上是pair<int, const char*>,而value_type可能是pair<const int, string>。因此,我们有可能通过转换参数和/而直接在地图中创建value_type对象,而不是创建临时value_type对象并将复制到容器中。或移动其成员。

另一方面,如果这样做也会很好:

mymap.insert({7,"seven"});

但这个清单实际上不是表达!因此,编译器无法推断出第二次重载的P.第一个重载仍然可行,因为您可以使用这样的列表复制初始化pair<const int,string>参数。

答案 1 :(得分:4)

n1858中添加了模板通用引用重载,其基本原理(适用于map,但同样明确适用于multimap):

  

其中两个insert签名是新的。已添加它们以允许从value_type以外的右值类型移动,这些类型可转换为value_type。当P实例化为左值时,参数将被复制到map中,否则会被移动到map(const限定符允许)。

(引用的另一个insert签名是insert-with-hint。)

我们还参考deque的基本原理(同样,明确引用其他容器):

  

将单个value_type插入(或追加,前置等)到容器中的所有成员函数都重载了一个成员函数,该函数通过rvalue引用接受该value_type,以便可以将单个value_type移动到容器中。这不仅使重量级类型的工作效率更高,而且还允许人们将可移动但不可复制的类型插入容器中。

显然,这些变化主要被视为增加;当时没有考虑模板重载可以完全替换原始(C ++ 03)insert。通过参考之前的n1771可以看出这一点,它为模板重载提供了一些动机,采用了不同的方法:

  

请注意,对于map和multimap,有两个新的插入重载,两者都使用非const key_type。无法从const key_type移动,因此为了能够将key_type移动到(多)映射中,必须使用一对。 const lvalue对和非const rvalue对都有重载,因此不会移动左值对。

pair<iterator, bool> insert(const value_type& x);  // CC
pair<iterator, bool> insert(const pair<key_type,mapped_type>& x);  // CC
pair<iterator, bool> insert(pair<key_type,mapped_type>&& x);

CCCopyConstructible的缩写。)

然后看来template重载已添加到mapmultimap,却没有意识到它们使const value_type &重载过多。您可以考虑提交缺陷报告以删除冗余重载。

答案 2 :(得分:2)

不同之处在于所使用的参考类型。第一个

std::unordered_map::insert(const value_type&)

在(C ++ 11)中使用现在称为左值引用的引用(C ++ 03)。这需要是常量。 C ++ 11引入了rvalue引用P&&,它不需要是const。 为了兼顾两者,提供了两个插入功能。

请参阅StackOverflow上的这个优秀答案wrt rvalue C ++ 11中的参考资料,我希望这有助于回答你的问题。

What does T&& (double ampersand) mean in C++11?

如你所说,可以使用rvalue-overload并传递一个const左值ref,但是 - 请参阅http://msdn.microsoft.com/en-us/library/dd293668.aspx

中的这个文字
  

通过重载函数以获取const左值引用或rvalue引用,您可以编写区分不可修改对象(左值)和可修改临时值(rvalues)的代码。

-Hannes