overload of std::unordered_map::insert
overload of std::unordered_map::insert
你能教我为什么两个
std::unordered_map::insert(const value_type&)
和
template<class P> std::unordered_map::insert(P&&)
是否存在于标准中?
我认为insert(P&&)
可以充当insert(const value_type&)
。
这两个重载
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>
参数。
在n1858中添加了模板通用引用重载,其基本原理(对于map
,但同样明确适用于multimap
):
insert
签名中有两个是新的。添加它们是为了允许从可转换为value_type
的value_type
以外的右值类型移动。当P
实例化为左值时,参数被复制到map
中,否则它被移动到map
中(const限定符允许)。
(引用的另一个insert
签名是插入提示。)
我们还提到了deque
的基本原理(同样,明确引用用于其他容器):
将单个value_type插入(或追加、预置等)到容器中的所有成员函数都会重载一个成员函数,该成员函数通过右值引用接受该value_type,以便可以将单个valuetype移动到容器中。这不仅使处理重载类型更加高效,还允许将可移动但不可复制的类型插入容器中。
很明显,这些变化主要被视为补充;当时没有考虑到模板重载可以完全取代原来的(C++03)CCD_ 21。这可以通过参考早期的n1771来看出,它为模板过载提供了一些动机,采用了一种不同的方法:
请注意,对于map和multimap,有两个新的insert重载,它们都采用了一对具有非常量key_type的重载。不能从const key_type中移动,因此必须使用一对才能将key_type移动到(多)映射中。常量左值对和非常量右值对都存在重载,因此左值对的值不会从中移动。
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
过载被添加到map
和multimap
,而没有意识到它们使const value_type &
过载成为冗余。您可以考虑提交一份缺陷报告,以消除多余的过载。
区别在于使用的引用类型。第一个
std::unordered_map::insert(const value_type&)
在(C++11)中使用一个现在称为左值引用的引用(C++03)。这需要常量。C++11引入了不需要常量的右值引用P&&
。为了实现这两个功能,提供了两个插入功能。
请在C++11中的StackOverflow wrt rvalue References上看到这个极好的答案,我希望这有助于回答你的问题。
T&;(双安培数)在C++11中的平均值?
正如您所说,可以使用右值重载并只传递常量左值ref,但是-请参阅http://msdn.microsoft.com/en-us/library/dd293668.aspx
通过重载函数以获取常量左值引用或右值引用,可以编写区分不可修改对象(左值)和可修改临时值(右值)的代码。
-Hannes
- 与C++std::map::insert行为相比,C#排序字典的效率
- std::map insert && hyperload 导致复制
- 为什么在以下示例中 std::map::insert 失败?
- map.insert:"Invalid arguments"错误与 pair<enum,vector<*>>
- 为什么缩小转换范围不能防止错误类型的map.insert()失败
- 当 std::map::insert 找到该元素时,它仍构造该对象的实例.我怎样才能阻止这种情况
- std::map::insert exception
- C++错误: map.insert(make_pair(struct, vector<struct>));
- C++std::map.insert()分段错误
- boost::interprocess::map insert 给出:对重载函数的不明确调用
- 为什么返回map.insert().second会引入无法访问的内存
- 如果map.insert失败,如何在不使用bad_alloc的情况下检查其失败
- 为什么编译顺序在使用 std::map::insert() 时有时会导致分段错误
- std::map.insert "could not deduce template argument for..."
- 如何根据插入对的存在来实现不同的“std::map insert()”行为
- Map::insert不起作用
- Std::map insert()提示位置:c++98和c++11的区别
- 在std::map::insert时出现分段错误
- 何时将node_type与std::map::insert一起使用
- 为什么map.insert()方法调用复制构造函数两次?