15

你能教我为什么两者

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

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

存在于标准中吗?

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

4

3 回答 3

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 的结果实际上是一个 whilepair<int, const char*>可能value_typepair<const int, string>。因此,我们有机会通过转换参数和/或移动其成员直接将对象创建到地图中,而不是创建临时value_type对象并将其复制到容器中。value_type

另一方面,如果这也能正常工作,那就太好了:

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

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

于 2013-02-06T13:09:58.077 回答
4

在n1858中添加了模板通用引用重载,理由是(对于map,但同样明确适用于multimap):

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

insert(提到的另一个签名是 insert-with-hint。)

我们还参考了以下理由deque(同样,明确引用了其他容器):

所有将单个 value_type 插入(或附加、前置等)到容器中的成员函数都被一个成员函数重载,该成员函数通过右值引用接受该 value_type,以便可以将单个 value_type 移动到容器中。这不仅使处理重量级类型更加高效,还允许将可移动但不可复制的类型插入容器中。

很明显,这些变化主要被认为是增加的;当时并没有考虑模板重载可以完全取代原来的(C++03)insert。这可以通过参考早期的n1771 看出,它为模板重载提供了一些动力,采用了不同的方法:

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

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);

CC是 的缩写CopyConstructible。)

然后似乎template添加了重载mapmultimap但没有意识到它们使const value_type &重载变得多余。您可能会考虑提交缺陷报告以删除多余的过载。

于 2013-02-06T10:28:51.363 回答
2

不同之处在于使用的参考类型。首先

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

使用引用 (C++03),现在在 (C++11) 中称为左值引用。这需要是常量。P&&C++11 引入了不需要是 const 的右值引用。为了允许两者,提供了两个插入函数。

请在 C++11 中的 StackOverflow wrt rvalue References 上查看这个出色的答案,我希望这有助于回答您的问题。

C++11 中的 T&&(双 & 符号)是什么意思?

正如您所说,可以使用 rvalue-overload 并只传递一个 const lvalue ref,但是 - 请参阅http://msdn.microsoft.com/en-us/library/dd293668.aspx中的此文本

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

-汉内斯

于 2013-02-06T09:47:11.447 回答