std::map<Key,T,Compare,Allocator>::insert
来自cppreference.com
<tbody>
</tbody>
<tbody class="t-dcl-rev t-dcl-rev-num ">
</tbody><tbody>
</tbody>
std::pair<iterator, bool> insert( const value_type& value ); |
(1) | |
template< class P > std::pair<iterator, bool> insert( P&& value ); |
(2) | (C++11 起) |
std::pair<iterator, bool> insert( value_type&& value ); |
(3) | (C++17 起) |
| (4) | ||
iterator insert( iterator pos, const value_type& value ); |
(C++11 前) | |
iterator insert( const_iterator pos, const value_type& value ); |
(C++11 起) | |
template< class P > iterator insert( const_iterator pos, P&& value ); |
(5) | (C++11 起) |
iterator insert( const_iterator pos, value_type&& value ); |
(6) | (C++17 起) |
template< class InputIt > void insert( InputIt first, InputIt last ); |
(7) | |
void insert( std::initializer_list<value_type> ilist ); |
(8) | (C++11 起) |
insert_return_type insert( node_type&& nh ); |
(9) | (C++17 起) |
iterator insert( const_iterator pos, node_type&& nh ); |
(10) | (C++17 起) |
如果容器尚未含有带等价键的元素,那么插入元素到容器中。
1-3) 插入
value。 重载 (2) 等价于
emplace(std::forward<P>(value)),且只有在 std::is_constructible<value_type, P&&>::value == true 时才会参与重载决议。4-6) 插入
value 到尽可能接近正好在 pos 之前的位置。 重载 (5) 等价于
emplace_hint(hint, std::forward<P>(value)),且只有在 std::is_constructible<value_type, P&&>::value == true 时才会参与重载决议。9) 如果
nh 是空的节点句柄,那么什么都不做。否则插入 nh 所拥有的元素到容器,如果容器尚未含有拥有等价于 nh.key() 的键的元素。如果 nh 非空且 get_allocator() != nh.get_allocator(),那么行为未定义。10) 如果
nh 是空的节点句柄,那么什么都不做并返回尾迭代器。否则,插入 nh 所拥有的元素到容器,如果容器尚未含有拥有等价于 nh.key() 的键的元素,并返回指向拥有等于 nh.key() 的键的元素的迭代器(无关乎插入成功还是失败)。如果插入成功,那么从 nh 移动,否则它保持该元素的所有权。元素被插入到尽可能接近正好在 pos 之前的位置。如果 nh 非空且 get_allocator() != nh.get_allocator(),那么行为未定义。没有迭代器或引用会失效。如果插入成功,在元素被节点句柄持有时所获取的指向元素的指针或引用均会失效,而在元素被提取之前所获取的指向它指针和引用则变为有效。(C++17 起)
参数
| pos | - | 指向新元素将被插入位置之前的迭代器 |
| value | - | 要插入的值 |
| first, last | - | 要插入的元素范围的迭代器对 |
| ilist | - | 插入值来源的初始化器列表 |
| nh | - | 兼容的结点句柄 |
| 类型要求 | ||
-InputIt 必须满足老式输入迭代器 (LegacyInputIterator) 。
| ||
返回值
1-3) 由一个指向被插入元素(或指向妨碍插入的元素)的迭代器和一个当且仅当发生插入时被设为
true 的 bool 值构成的对偶。4-6) 指向被插入元素或指向妨碍插入的元素的迭代器。
7,8) (无)
9)
insert_return_type 类型的对象,它的成员初始化如下:
- 如果
nh为空,那么inserted是false,position是end(),且node为空。 - 否则如果发生插入,那么
inserted是true,position指向被插入元素,且node为空。 - 如果插入失败,那么
inserted是false,node拥有nh的先前值,且position指向拥有等价于nh.key()的键的元素。
10) 如果
nh 为空就是尾迭代器,如果插入发生就是指向被插入元素的迭代器,而如果插入失败就是指向拥有等价于 nh.key() 的键的元素的迭代器。异常
1-6) 如果任何操作抛出异常,那么插入无效果(强异常保证)。
7,8) 如果任何操作抛出异常,那么程序在合法状态(基础异常保证)。
9,10) 如果任何操作抛出异常,那么插入无效果,
nh 保持不变(强异常保证)。复杂度
1-3) 与容器大小成对数,
O(log(size()))。4-6) 如果插入恰好发生在正好在
pos 之后(C++11 前)之前(C++11 起) 的位置,那么是均摊常数,否则与容器大小成对数。7,8)
O(N·log(size() + N)),其中 N 是要插入的元素数。9) 与容器大小成对数,
O(log(size()))。10) 如果插入恰好发生在正好在
pos 之前 的位置,那么是均摊常数,否则与容器大小成对数。注解
有提示插入 (4-6) 不返回布尔值,这是为了与顺序容器上的定位插入,如 std::vector::insert 签名兼容。这使得可以创建泛型插入器,例如 std::inserter。检查有提示插入是否成功的一种方式是比较插入前后的 size()。
示例
运行此代码
#include <iomanip>
#include <iostream>
#include <map>
#include <string>
using namespace std::literals;
template<typename It>
void print_insertion_status(It it, bool success)
{
std::cout << "插入 " << it->first
<< (success ? " 成功\n" : " 失败\n");
}
int main()
{
std::map<std::string, float> heights;
// 重载 3:从右值引用插入
const auto [it_hinata, success] = heights.insert({"Hinata"s, 162.8});
print_insertion_status(it_hinata, success);
{
// 重载 1:从左值引用插入
const auto [it, success2] = heights.insert(*it_hinata);
print_insertion_status(it, success2);
}
{
// 重载 2:经由转发到 emplace 插入
const auto [it, success] = heights.insert({"Kageyama", 180.6});
print_insertion_status(it, success);
}
{
// 重载 6:带位置提示从右值引用插入
const std::size_t n = std::size(heights);
const auto it = heights.insert(it_hinata, {"Azumane"s, 184.7});
print_insertion_status(it, std::size(heights) != n);
}
{
// 重载 4:带位置提示从左值引用插入
const std::size_t n = std::size(heights);
const auto it = heights.insert(it_hinata, *it_hinata);
print_insertion_status(it, std::size(heights) != n);
}
{
// 重载 5:带位置提示经由转发到 emplace 插入
const std::size_t n = std::size(heights);
const auto it = heights.insert(it_hinata, {"Tsukishima", 188.3});
print_insertion_status(it, std::size(heights) != n);
}
auto node_hinata = heights.extract(it_hinata);
std::map<std::string, float> heights2;
// 重载 7:从范围插入
heights2.insert(std::begin(heights), std::end(heights));
// 重载 8:从 initializer_list 插入
heights2.insert({{"Kozume"s, 169.2}, {"Kuroo", 187.7}});
// 重载 9:插入结点
const auto status = heights2.insert(std::move(node_hinata));
print_insertion_status(status.position, status.inserted);
node_hinata = heights2.extract(status.position);
{
// 重载 10:插入结点带位置提示
const std::size_t n = std::size(heights2);
const auto it = heights2.insert(std::begin(heights2), std::move(node_hinata));
print_insertion_status(it, std::size(heights2) != n);
}
// 打印结果 map
std::cout << std::left << '\n';
for (const auto& [name, height] : heights2)
std::cout << std::setw(10) << name << " | " << height << "cm\n";
}
输出:
插入 Hinata 成功
插入 Hinata 失败
插入 Kageyama 成功
插入 Azumane 成功
插入 Hinata 失败
插入 Tsukishima 成功
插入 Hinata 成功
插入 Hinata 成功
Azumane | 184.7cm
Hinata | 162.8cm
Kageyama | 180.6cm
Kozume | 169.2cm
Kuroo | 187.7cm
Tsukishima | 188.3cm
缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
| 缺陷报告 | 应用于 | 出版时的行为 | 正确行为 |
|---|---|---|---|
| LWG 233 | C++98 | pos 只是提示,可以完全忽略
|
必须在尽可能接近正好在pos 之前的位置插入
|
| LWG 264 | C++98 | 重载 (7) 的复杂度在范围 [first, last)已经按 Compare 排序的情况下要求是线性
|
取消这种情况下的线性复杂度要求 |
| LWG 316 | C++98 | 未指定重载 (1) 返回的哪个 bool 值表示插入成功
|
返回 true 表示插入成功
|
| LWG 2005 | C++11 | 重载 (2,5) 的描述质量较差 | 改进描述 |
参阅
(C++11) |
原位构造元素 (公开成员函数) |
(C++11) |
使用提示原位构造元素 (公开成员函数) |
(C++17) |
插入元素,或若键已存在则赋值给当前元素 (公开成员函数) |
| 创建拥有从实参推出的类型的 std::insert_iterator (函数模板) |