CppDS.com

C++ 98 11 14 17 20 手册

std::map<Key,T,Compare,Allocator>::insert

来自cppreference.com
< cpp‎ | container‎ | map
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 hint, const value_type& value );
(C++11 前)
iterator insert( const_iterator hint, const value_type& value );
(C++11 起)
template< class P >
iterator insert( const_iterator hint, P&& value );
(5) (C++11 起)
iterator insert( const_iterator hint, 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 hint, 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 到尽可能接近,恰好前于(C++11 起) hint 的位置。重载 (4) 等价于 emplace_hint(hint, std::forward<P>(value)) ,且仅若 std::is_constructible<value_type, P&&>::value == true 才参与重载决议。
7) 插入来自范围 [first, last) 的元素。若范围中的多个元素拥有比较等价的关键,则插入哪个元素是未指定的(待决的 LWG2844 )。
8) 插入来自 initializer_list ilist 的元素。若范围中的多个元素拥有比较等价的关键,则插入哪个元素是未指定的(待决的 LWG2844 )。
9)nh 是空的结点把柄,则不做任何事。否则插入 nh 所占有的元素到容器,若容器尚未含有拥有等价于 nh.key() 的关键的元素。若 nh 非空且 get_allocator() != nh.get_allocator() 则行为未定义。
10)nh 是空的结点把柄,则不做任何事并返回尾迭代器。否则,插入 nh 所占有的元素到容器,若容器尚未含有拥有等价于 nh.key() 的关键的元素,并返回指向拥有等于 nh.key() 的关键的元素的迭代器(无关乎插入成功还是失败)。若插入成功,则从 nh 移动,否则它保持该元素的所有权。元素被插入到尽可能接近正好先于 hint 的位置。若 nh 非空且 get_allocator() != nh.get_allocator() 则行为未定义。

没有迭代器或引用被非法化。若插入成功,则在结点把柄保有元素时获得的指向该元素的指针和引用被非法化,而在提取前获得的指向元素的指针和引用变得合法。 (C++17 起)

参数

hint -

用作搜索开始位置的建议的迭代器

(C++11 前)

指向将插入新元素到其前的位置的迭代器

(C++11 起)
value - 要插入的值
first, last - 要插入的元素范围
ilist - 插入值来源的 initializer_list
nh - 兼容的结点把柄
类型要求
-
InputIt 必须满足遗留输入迭代器 (LegacyInputIterator) 的要求。

返回值

1-3) 返回由指向被插入元素的迭代器(或阻止插入的元素的迭代器)和指代插入是否发生的 bool 组成的 pair 。
4-6) 返回指向被插入元素的迭代器,或指向阻止插入的元素的迭代器。
7-8) (无)
9) 返回 insert_return_type ,其成员初始化如下:若 nh 为空,则 insertedfalsepositionend() ,而 node 为空。否则发生插入, insertedtrueposition 指向被插入元素,而 node 为空。若插入失败,则 insertedfalsenode 拥有 nh 的先前值,而 position 指向拥有等价于 nh.key() 的关键的元素。
10)nh 为空则为尾迭代器,若插入发生则为指向被插入元素的迭代器,而若插入失败则为指向拥有等价于 nh.key() 的关键的元素的迭代器。

异常

1-6) 若任何操作抛出异常,则插入无效果(强异常保证)。
7-8) 若任何操作抛出异常,则程序在合法状态(基础异常保证)。
9-10) 若任何操作抛出异常,则插入无效果, nh 保持不变(强异常保证)。

复杂度

1-3) 与容器大小成对数, O(log(size()))
4-6) 若插入恰好发生在 hint 的位置则为均摊常数,否则与容器大小成对数。
(C++11 前)
4-6) 若插入恰好发生在 hint 的位置则为均摊常数,否则与容器大小成对数。
(C++11 起)
7-8) O(N*log(size() + N)) ,其中 N 是要插入的元素数。
9) 与容器大小成对数, O(log(size()))
10) 若插入恰好发生在 hint 的位置则为均摊常数,否则与容器大小成对数。


注解

有提示插入 (4-6) 不返回 bool ,这是为了与顺序容器上的定位插入,如 std::vector::insert 签名兼容。这使得可以创建泛型插入器,例如 std::inserter 。检查有提示插入是否成功的一种方式是比较插入前后的 size()

示例

#include <iomanip>
#include <iostream>
#include <map>
#include <string>
 
using namespace std::literals;
 
template<typename It>
void printInsertionStatus(It it, bool success)
{
    std::cout << "Insertion of " << it->first << (success ? " succeeded\n" : " failed\n");
}
 
int main()
{
    std::map<std::string, float> karasunoPlayerHeights;
 
    // 重载 3 :从右值引用插入
    const auto [it_hinata, success] = karasunoPlayerHeights.insert({"Hinata"s, 162.8});
    printInsertionStatus(it_hinata, success);
 
    {
        // 重载 1 :从左值引用插入
        const auto [it, success2] = karasunoPlayerHeights.insert(*it_hinata);
        printInsertionStatus(it, success2);
    }
    {
        // 重载 2 :经由转发到 emplace 插入
        const auto [it, success] = karasunoPlayerHeights.insert({"Kageyama", 180.6});
        printInsertionStatus(it, success);
    }
 
    {
        // 重载 6 :带位置提示从右值引用插入
        const std::size_t n = std::size(karasunoPlayerHeights);
        const auto it = karasunoPlayerHeights.insert(it_hinata, {"Azumane"s, 184.7});
        printInsertionStatus(it, std::size(karasunoPlayerHeights) != n);
    }
    {
        // 重载 4 :带位置提示从左值引用插入
        const std::size_t n = std::size(karasunoPlayerHeights);
        const auto it = karasunoPlayerHeights.insert(it_hinata, *it_hinata);
        printInsertionStatus(it, std::size(karasunoPlayerHeights) != n);
    }
    {
        // 重载 5 :带位置提示经由转发到 emplace 插入
        const std::size_t n = std::size(karasunoPlayerHeights);
        const auto it = karasunoPlayerHeights.insert(it_hinata, {"Tsukishima", 188.3});
        printInsertionStatus(it, std::size(karasunoPlayerHeights) != n);
    }
 
    auto node_hinata = karasunoPlayerHeights.extract(it_hinata);
    std::map<std::string, float> playerHeights;
 
    // 重载 7 :从范围插入
    playerHeights.insert(std::begin(karasunoPlayerHeights), std::end(karasunoPlayerHeights));
 
    // 重载 8 :从 initializer_list 插入
    playerHeights.insert({{"Kozume"s, 169.2}, {"Kuroo", 187.7}});
 
 
    // 重载 9 :插入结点
    const auto status = playerHeights.insert(std::move(node_hinata));
    printInsertionStatus(status.position, status.inserted);
 
    node_hinata = playerHeights.extract(status.position);
    {
        // 重载 10 :插入结点带位置提示
        const std::size_t n = std::size(playerHeights);
        const auto it = playerHeights.insert(std::begin(playerHeights), std::move(node_hinata));
        printInsertionStatus(it, std::size(playerHeights) != n);
    }
 
 
    // 打印结果 map
    std::cout << std::left << '\n';
    for (const auto& [name, height] : playerHeights)
        std::cout << std::setw(10) << name << " | " << height << "cm\n";
}

输出:

Insertion of Hinata succeeded
Insertion of Hinata failed
Insertion of Kageyama succeeded
Insertion of Azumane succeeded
Insertion of Hinata failed
Insertion of Tsukishima succeeded
Insertion of Hinata succeeded
Insertion of Hinata succeeded
 
Azumane    | 184.7cm
Hinata     | 162.8cm
Kageyama   | 180.6cm
Kozume     | 169.2cm
Kuroo      | 187.7cm
Tsukishima | 188.3cm

参阅

(C++11)
原位构造元素
(公开成员函数)
使用提示原位构造元素
(公开成员函数)
插入元素,或若键已存在则赋值给当前元素
(公开成员函数)
关闭