std::地图和它的兄弟姐妹(std::多映射,std::unordered_map/多映射)曾经是我最喜欢的容器,当我做竞争编程。事实上,我仍然喜欢它们(尽管现在使用频率较低)。随着现代C++,我们现在有更多的理由使用std:地图。因此,我决定写一篇总结这些新功能的文章来讨论这个话题。所以,没有太多的胡言乱语,让我们直接潜入。
std::地图::包含(C++20)
std::map::contains
成员函数是走向代码表达性的好一步。我也厌倦了写作:
Java
Ⅹ
如果(自动搜索 = freq_of freq_of。查找(2);搜索! = freq_of。结束()) |
2
cout<<"Found"<<endl;
3
}
4
假设为 freq_of = 映射<uint32_t,uint32_t>{3, 1},{1, 1},{2},1];
相反,从 C++20 开始,您可以编写:
Java
x
1
1
如果(freq_of。包含(2)|
2
cout<<"Found"<<endl;
3
}
我们编写的代码是先为人类消费而编写的,其次为计算机所编写的。
– 约翰·桑梅斯
std::地图::try_emplace (C++17)
在插入地图时,我们有两种不同的可能性:
- 密钥尚不存在。创建新的键值对。
- 密钥确实存在。拿现有项目并修改它。
插入元素的典型方法
std::map
是通过使用
operator[ ]
,
std::map::insert
或
std::map::emplace
.但是,在所有这些情况下,我们必须承担默认/专用构造函数或赋值调用的成本。最糟糕的是,如果一个项目已经存在,我们必须删除新创建的项。
Java
X
1
14
1
int主() |
2
矢量 v=345873524+;
3
地图<uint32_tuint32_tuint32_t>freq_of;
5
用于(const自动&nv) |
6
如果(康斯特自动&=它插入=freq_offreq_of。位置(n1!插入){
7
它->第二 =; // 已存在
8
}
9
}
10
11
12
13
返回EXIT_SUCCESS;
14
}
相反
Java
X
1
1
如果(康斯特自动&=它插入=freq_offreq_of。try_emplace(n1!插入){
2
它->第二 =;
3
}
但是,C++17,有这个
std::try_emplace:::仅在键尚不存在时创建项的方法。这会提高性能,以防创建此类对象的成本很高。
尽管上述示例没有展示创建项目的昂贵性。但是,是的!每当你遇到这样的情况,必须知道如何处理它
std::map::try_emplace
.
std::地图::insert_or_assign (C++17)
无论如何,当您必须插入元素时。为了方便起见,您使用
std::地图::运算符=。这是确定(和
危险)!除非对插入或赋值有任何限制
e. 已分配),您必须删除所有小于当前元素的元素。
在这种情况下,
std::map::operator[ ]
是不可行的。而std::map::insert_or_assign
比 更合适,返回的信息比 std::map::operator[ ]
更多。它也不要求映射类型的默认构造性。请考虑以下示例。
Java
x
1
19
[int 主()]
2
矢量 v=83958+;
3
地图<uint32_tuint32_tuint32_t>freq_of;
4
5
用于(自动 &nv) |
6
康斯特自动&is_insertedis_inserted=freq_of。insert_or_assign(n1);
7
if (!is_inserted)\ // 删除所有较小的元素, 然后当前一个, 如果重复
9
freq_of.擦除(开始)freq_of它);
10
}
11
}
12
13
断言((freq_of=decltype(freq_of)
14
[81],
15
16
}));
17
18
返回EXIT_SUCCESS;
19
}
std::地图::插入带提示 (C++11/17)
在
std::map
采取
O(log(n))
时间。对于插入新项目,这是相同的。因为插入它们的位置必须向上。天真地插入
M
因此,新项目将采取
O(M * log(n))
时间。
为了提高效率,
std::map
插入函数接受可选的插入提示参数。插入提示基本上是一个活动器,它指向要插入的项目的未来位置附近。如果提示是正确的,那么我们得到摊销
O(1)
插入时间。
从性能的角度来看,当项的插入顺序有些可预测时,这非常有用。例如:
Java