std::set<Key,Compare,Allocator>::insert

来自cppreference.com
< cpp‎ | container‎ | set
 
 
 
 
std::pair<iterator, bool> insert( const value_type& value );
(1) (C++26 起为 constexpr)
std::pair<iterator, bool> insert( value_type&& value );
(2) (C++11 起)
(C++26 起为 constexpr)
(3)
iterator insert( iterator pos, const value_type& value );
(C++11 前)
iterator insert( const_iterator pos, const value_type& value );
(C++11 起)
(C++26 起为 constexpr)
iterator insert( const_iterator pos, value_type&& value );
(4) (C++11 起)
(C++26 起为 constexpr)
template< class InputIt >
void insert( InputIt first, InputIt last );
(5) (C++26 起为 constexpr)
void insert( std::initializer_list<value_type> ilist );
(6) (C++11 起)
(C++26 起为 constexpr)
insert_return_type insert( node_type&& nh );
(7) (C++17 起)
(C++26 起为 constexpr)
iterator insert( const_iterator pos, node_type&& nh );
(8) (C++17 起)
(C++26 起为 constexpr)
template< class K >
std::pair<iterator, bool> insert( K&& x );
(9) (C++23 起)
(C++26 起为 constexpr)
template< class K >
iterator insert( const_iterator pos, K&& x );
(10) (C++23 起)
(C++26 起为 constexpr)

尝试将元素插入到 *this

  • 如果容器含拥有等价关键的元素,那么什么也不做。
  • 否则将元素插入到 *this
1-4) 插入 value。如果有提供 pos,那么就会插入到尽可能接近正好在 pos 之前的位置。
1,3) 如果 value_type可复制插入 (CopyInsertable) set 中,那么行为未定义。
2,4) 如果 value_type可移动插入 (MoveInsertable) set 中,那么行为未定义。
(C++11 起)
5) 插入来自范围 [firstlast) 的元素。
6) 插入来自初始化器列表 ilist 的元素。
7) 如果 nh 是空的节点句柄,那么什么都不做。否则插入 nh 所拥有的元素到容器,如果容器尚未含有拥有等价于 nh.key() 的键的元素。如果 nh 非空且 get_allocator() != nh.get_allocator(),那么行为未定义。
8) 如果 nh 是空的节点句柄,那么什么都不做并返回尾迭代器。否则,插入 nh 所拥有的元素到容器,如果容器尚未含有拥有等价于 nh.key() 的键的元素,并返回指向拥有等于 nh.key() 的键的元素的迭代器(无关乎插入成功还是失败)。如果插入成功,那么从 nh 移动,否则它保持该元素的所有权。元素被插入到尽可能接近正好在 pos 之前的位置。如果 nh 非空且 get_allocator() != nh.get_allocator(),那么行为未定义。
9,10)std::forward<K>(x) 构造一个 value_type 类型的对象 u,然后将 u 插入 *this 中。在构造 u 之前就会使用 x 透明地确定是否存在等价关键。
如果满足以下任意条件,那么行为未定义:
9) 此重载只有在 Compare 透明时才会参与重载决议。
10) u 会被插入到尽可能接近正好在 pos 之前的位置。
此重载只有在满足以下所有条件时才会参与重载决议:

没有迭代器或引用会失效。如果插入成功,在元素被节点句柄持有时所获取的指向元素的指针或引用均会失效,而在元素被提取之前所获取的指向它指针和引用则变为有效。(C++17 起)

参数

pos - 指向新元素将被插入位置之前的迭代器
value - 要插入的元素值
first, last - 要插入的源元素范围的迭代器对
ilist - 插入值来源的初始化器列表
nh - 兼容的节点把柄
x - 可以与键进行透明比较的任何类型的值
类型要求
-
InputIt 必须满足老式输入迭代器 (LegacyInputIterator)

返回值

1,2) 由一个指向被插入元素(或指向妨碍插入的元素)的迭代器和一个当且仅当发生插入时被设为 truebool 值构成的对偶。
3,4) 指向被插入元素或指向妨碍插入的元素的迭代器。
7) insert_return_type 类型的对象,它的成员初始化如下:
  • 如果 nh 为空,那么 insertedfalsepositionend(),且 node 为空。
  • 否则如果发生插入,那么 insertedtrueposition 指向被插入元素,且 node 为空。
  • 如果插入失败,那么 insertedfalsenode 拥有 nh 的先前值,且 position 指向拥有等价于 nh.key() 的键的元素。
8) 如果 nh 为空就是尾迭代器,如果插入发生就是指向被插入元素的迭代器,而如果插入失败就是指向拥有等价于 nh.key() 的键的元素的迭代器。
9) 由一个指向被插入元素(或指向妨碍插入的元素)的迭代器和一个当且仅当发生插入时被设为 truebool 值构成的对偶。
10) 指向被插入元素或指向妨碍插入的元素的迭代器。

异常

如果在插入单个元素的情况下有任何操作抛出了异常,那么插入无效果。

复杂度

给定 Nsize()

1,2) log(N)
3,4) 如果插入恰好发生在正好在 pos 之前的位置,那么是均摊常数,否则是 log(N)
5,6) log(N+M),其中 M 是要插入的元素数。
7) log(N)
8) 如果插入恰好发生在正好在 pos 之前的位置,那么是均摊常数,否则是 log(N)
9) log(N)
10) 如果插入恰好发生在正好在 pos 之前的位置,那么是均摊常数,否则是 log(N)

注解

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

重载 (5,6) 通常实现为循环,其中以 end() 作为提示调用重载 (3);它们对后附最小元素大于 *this 中最大元素的有序序列(例如另一 std::set)优化。

如果范围中的多个元素的键比较相等,那么未指定哪个元素会被插入(参考待决的 LWG2844)。

功能特性测试 标准 功能特性
__cpp_lib_associative_heterogeneous_insertion 202311L (C++26) 有序无序关联容器中剩余成员函数的异质重载。(9,10)

示例

#include <cassert>
#include <iostream>
#include <set>
 
int main()
{
    std::set<int> set;
 
    auto result_1 = set.insert(3);
    assert(result_1.first != set.end()); // 它是有效的迭代器
    assert(*result_1.first == 3);
    if (result_1.second)
        std::cout << "插入完成\n";
 
    auto result_2 = set.insert(3);
    assert(result_2.first == result_1.first); // 相同的迭代器
    assert(*result_2.first == 3);
    if (!result_2.second)
        std::cout << "未进行插入\n";
}

输出:

插入完成
未进行插入

缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

缺陷报告 应用于 出版时的行为 正确行为
LWG 233 C++98 pos 只是提示,可以完全忽略 必须在尽可能接近正好在
pos 之前的位置插入
LWG 264 C++98 重载 (5) 的复杂度在范围 [firstlast) 已经按 Compare 排序的情况下要求是线性 取消这种情况下的线性复杂度要求
LWG 316 C++98 未指定重载 (1) 的返回值中用哪个 bool 值表示插入成功 true 表示插入成功

参阅

(C++11)
原位构造元素
(公开成员函数)
使用提示原位构造元素
(公开成员函数)
创建拥有从实参推出的类型的 std::insert_iterator
(函数模板)