C++ 在映射或无序映射中需要insert()吗?
我看到许多示例通过C++ 在映射或无序映射中需要insert()吗?,c++,C++,我看到许多示例通过操作符[]将项目添加到映射或无序映射,如下所示: int main() { unordered_map <string, int> m; m["foo"] = 42; cout << m["foo"] << endl; } intmain(){ 无序地图m; m[“foo”]=42; 不能他们不是 operator[]将覆盖此键的值(如果存在),而insert将不覆盖 如果使用operator[]插入元素,则预计会稍
操作符[]
将项目添加到映射
或无序映射
,如下所示:
int main() {
unordered_map <string, int> m;
m["foo"] = 42;
cout << m["foo"] << endl;
}
intmain(){
无序地图m;
m[“foo”]=42;
不能他们不是
operator[]
将覆盖此键的值(如果存在),而insert
将不覆盖
如果使用operator[]
插入元素,则预计会稍微慢一点(有关详细信息,请参见下面的@MatthieuM注释),但这在这里并不重要
而std::map::insert
返回std::pair
,其中.second
将告诉您该值是插入的还是已经存在
关于您的评论:您不能有两个具有相同键和不同值的元素。这不是一个多重映射
如果地图中有一个元素与您尝试插入的键相同,则:
运算符[]
将覆盖现有值
std::map::insert
不会做任何事情。*返回一个std::pair
,其中第二个将是false
(表示“新元素未插入,因为这样的键已经存在”),而。第一个将指向找到的元素
*感谢@luk32给出的注释/备注,我改变了这一点;但通过写“不会做任何事情”,我并不是字面意思,我的意思是它不会改变现有元素的值,我在一定程度上不同意Kiril的答案,我认为它不完整,所以我给出了我的答案
根据std::map::operator[]
相当于某个insert()
调用。因此,我认为他说该值将被覆盖是错误的。
上面写着:“返回值
如果不存在键为key的元素,则引用新元素的映射值。否则,将返回对现有元素的映射值的引用。“
因此它似乎是一个方便的包装器。insert()
,但是它有重载的优点,因此它在一个名称下提供了更多的功能
我向Kiril指出,乍一看,它们的功能似乎有点不同,但他提供的示例并不完全相同
因此,作为使用insert
的示例/理由,我要指出,一次插入许多元素,或者使用hint
(调用中的3-6)
那么,在映射或无序映射中是否需要insert()呢?
我会说是的。此外,没有必要使用操作符[]
,因为它可以使用insert
来模拟/实现,而另一种方法是不可能的!它只是提供了更多的功能。但是,编写类似(insert(std::make_pair(key,T())。首先)->其次)
(之后)的东西似乎比[/code>更麻烦
因此,是否有理由改用插入成员函数?
我想说的是,对于重叠功能,绝对不是。使用insert()
可以在某些情况下帮助提高性能(更具体地说,对于std::map
,因为搜索时间是O(log(n))
,而不是常数摊销)。举以下常见示例:
std::map<int, int> stuff;
// stuff is populated, possibly large:
auto iterator = stuff.find(27);
if(stuff.end() != iterator)
{
// subsequent "find", set to 15
iterator->second = 15;
}
else
{
// insert with value of 10
stuff[27] = 10;
}
上面的代码只尝试查找一个元素一次,从而降低了算法复杂性。对于频繁的操作,这可以显著提高性能。这两个元素并不等效。insert
不会覆盖现有值,它返回一个对,其中迭代器
是密钥的位置,regardles它是否已经存在。布尔值指示插入是否发生
操作符[]
有效地对键执行下限
。如果该操作的结果是具有相同键的迭代器
,则返回对该值的引用。如果不是,则插入具有默认构造值的新节点,然后返回对该值的引用。这就是为什么操作符[]
是一个非常量成员-如果键值不存在,它会自动激活该键值。如果值类型的构造成本很高,这可能会影响性能。
还要注意的是,在C++11中,我们有一个emplace
方法,其工作原理与insert
几乎相同,只是如果发生insert,它会根据转发的参数构造键值对。Ok,那么如果插入两个具有相同键值的项会发生什么情况呢?该键值的数据不会被覆盖。括号表示法为eqivalent to(*((m.insert(value\u type(k,data\u type()))).first)).second=data;
(借用脚注3)。也就是说,它插入带有默认构造数据的键,然后获取返回的迭代器(the。first
),它要么指向旧的、未修改的键值对(如果存在),要么指向刚添加的新键值对,并将与该键值关联的数据(第二个
)设置为所需的值。操作符[]
也不会做任何事情。T::operator=
使用从map::operator[]获得的引用
可以。您可以使用insert()获得相同的引用
。这取决于严格的语义分析。但我认为我就在这里,虽然我仍然理解你更人性化的方法,但它们的行为似乎有所不同。但当你分解代码时,它们就不是了。只是这里发生了更多的事mymap[“答案”]=42
比看起来的要慢。至少在我看来。@KirilKirov:操作符[]
预计会慢一点,但我不会说这是因为检查;操作符[]
和插入
执行相同数量的检查。操作符[]
对于直接插入速度较慢,因为它首先生成默认值
// try to insert 27 -> 10
auto result = stuff.insert(std::make_pair(27, 10));
// already existed
if(false == result.second)
{
// update to 15, already exists
result.first->second = 15;
}