Namespaces
Variants

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

From cppreference.net

(1)
set ( ) ;
(C++11 前)
set ( ) : set ( Compare ( ) ) { }
(C++11 起)
(C++26 起为 constexpr)
explicit set ( const Compare & comp,
const Allocator & alloc = Allocator ( ) ) ;
(2) (C++26 起为 constexpr)
explicit set ( const Allocator & alloc ) ;
(3) (C++11 起)
(C++26 起为 constexpr)
template < class InputIt >

set ( InputIt first, InputIt last,
const Compare & comp = Compare ( ) ,

const Allocator & alloc = Allocator ( ) ) ;
(4) (C++26 起为 constexpr)
template < class InputIt >

set ( InputIt first, InputIt last,
const Allocator & alloc )

: set ( first, last, Compare ( ) , alloc ) { }
(5) (C++14 起)
(C++26 起为 constexpr)
set ( const set & other ) ;
(6) (C++26 起为 constexpr)
set ( const set & other, const Allocator & alloc ) ;
(7) (C++11 起)
(C++26 起为 constexpr)
set ( set && other ) ;
(8) (C++11 起)
(C++26 起为 constexpr)
set ( set && other, const Allocator & alloc ) ;
(9) (C++11 起)
(C++26 起为 constexpr)
set ( std:: initializer_list < value_type > init,

const Compare & comp = Compare ( ) ,

const Allocator & alloc = Allocator ( ) ) ;
(10) (C++11 起)
(C++26 起为 constexpr)
set ( std:: initializer_list < value_type > init,

const Allocator & alloc )

: set ( init, Compare ( ) , alloc ) { }
(11) (C++14 起)
(C++26 起为 constexpr)
template < container-compatible-range < value_type > R >

set ( std:: from_range_t , R && rg,
const Compare & comp = Compare ( ) ,

const Allocator & alloc = Allocator ( ) ) ;
(12) (C++23 起)
(C++26 起为 constexpr)
template < container-compatible-range < value_type > R >

set ( std:: from_range_t , R && rg,
const Allocator & alloc )

: set ( std:: from_range , std:: forward < R > ( rg ) , Compare ( ) , alloc ) { }
(13) (C++23 起)
(C++26 起为 constexpr)

从多种数据源构造新容器,并可选择使用用户提供的分配器 alloc 或比较函数对象 comp

1-3) 构造一个空容器。
4,5) 使用范围 [ first , last ) 的内容构造容器。
如果 [ first , last ) 不是有效的 范围 ,则行为未定义。
6,7) 构造容器并复制 other 的内容。

若未提供 alloc ,则通过调用 std:: allocator_traits < allocator_type > ::
select_on_container_copy_construction ( other. get_allocator ( ) )
获取分配器。

(C++11 起)

类模板实参推导 期间,仅首个实参参与容器 Allocator 模板形参的推导。

(C++23 起)
8,9) 使用移动语义构造容器,内容来自 other 。如果未提供 alloc ,则通过从属于 other 的分配器进行移动构造来获取分配器。

类模板实参推导 期间,仅第一个实参参与容器 Allocator 模板形参的推导。

(C++23 起)
10,11) 使用初始化列表 init 的内容构造容器。
12,13) 使用 rg 的内容构造容器。

目录

参数

alloc - 用于此容器所有内存分配的分配器
comp - 用于所有键值比较的比较函数对象
first, last - 定义待复制元素源 范围 的迭代器对
other - 用作源容器以初始化当前容器元素的其他容器
init - 用于初始化容器元素的初始化列表
rg - 容器兼容范围 ,即元素可转换为 value_type input_range
类型要求
-
InputIt 必须满足 LegacyInputIterator 要求
-
Compare 必须满足 Compare 要求
-
Allocator 必须满足 Allocator 要求

复杂度

1-3) 常量。
4,5) N·log(N) 其中 N std:: distance ( first, last ) 的返回值。通常情况下时间复杂度为 N·log(N),若 [ first , last ) 已按 value_comp ( ) 排序,则时间复杂度为线性。
6,7) other 的大小成线性关系。
8,9) 常数复杂度。若提供 alloc alloc ! = other. get_allocator ( ) ,则为线性复杂度。
10,11) N·log(N) 其中 N init. size ( ) ,通常情况下的复杂度,若 init 已按 value_comp ( ) 排序则为 N 的线性复杂度。
12,13) N·log(N) 其中 N ranges:: distance ( rg ) 的通用情况,若 rg 已按 value_comp ( ) 排序则为 N 的线性复杂度。

异常

Allocator::allocate 的调用可能抛出异常。

注释

在容器移动构造后(重载 ( 8,9 ) ),指向 other 的引用、指针和迭代器(除尾后迭代器外)保持有效,但会引用现在位于 * this 中的元素。当前标准通过 [container.reqmts]/67 中的总体说明提供此保证,更直接的保证正在通过 LWG issue 2321 进行审议。

如果范围内多个元素的键比较等价,则未指定插入哪个元素(待解决 LWG2844 )。

尽管在C++23之前并非正式要求,但某些实现在早期模式中已将模板参数 Allocator 置于 非推导语境 中。

功能测试 标准 功能
__cpp_lib_containers_ranges 202202L (C++23) 支持范围 的构造与插入;重载版本 ( 12,13 )

示例

#include <cmath>
#include <iostream>
#include <set>
#include <string>
struct Point { double x, y; };
struct PointCmp
{
    bool operator()(const Point& lhs, const Point& rhs) const
    {
        return std::hypot(lhs.x, lhs.y) < std::hypot(rhs.x, rhs.y);
    }
};
std::ostream& operator<<(std::ostream& os, Point pt)
{
    return os << '(' << pt.x << ',' << pt.x << ')';
}
void println(auto rem, const auto& seq)
{
    std::cout << rem << '{';
    for (auto n{seq.size()}; const auto& elm : seq)
        std::cout << elm << (--n ? ", " : "");
    std::cout << "}\n";
}
int main()
{
    // (1) 默认构造函数
    std::set<std::string> a;
    a.insert("horse");
    a.insert("cat");
    a.insert("dog");
    println("1) a: ", a);
    // (4) 范围构造函数
    std::set<std::string> b(a.find("dog"), a.end());
    println("2) b: ", b);
    // (6) 拷贝构造函数
    std::set<std::string> c(a);
    c.insert("another horse");
    println("3) c: ", c);
    // (8) 移动构造函数
    std::set<std::string> d(std::move(a));
    println("4) d: ", d);
    println("5) a: ", a);
    // (10) 初始化列表构造函数
    std::set<std::string> e{"one", "two", "three", "five", "eight"};
    println("6) e: ", e);
    // 自定义比较
    std::set<Point, PointCmp> f = {{2, 5}, {3, 4}, {1, 1}};
    f.insert({1, -1}); // 此操作失败,因为 (1,-1) 的模长等于 (1,1)
    println("7) f: ", f);
    // (12) 范围构造函数
    const auto w = {"Eurybia", "Theia", "Rhea", "Aura", "Mnemosyne", "Mnemosyne"};
#if __cpp_lib_containers_ranges
    std::set<std::string> g(std::from_range, w); // 重载 (12)
#else
    std::set<std::string> g(w.begin(), w.end()); // 回退到 (4)
#endif
    println("8) g: ", g);
}

可能的输出:

1) a: {cat, dog, horse}
2) b: {dog, horse}
3) c: {another horse, cat, dog, horse}
4) d: {cat, dog, horse}
5) a: {}
6) e: {eight, five, one, three, two}
7) f: {(1,1), (3,3), (2,2)}
8) g: {Aura, Eurybia, Mnemosyne, Rhea, Theia}

缺陷报告

下列行为变更缺陷报告被追溯应用于先前发布的C++标准。

缺陷报告 适用范围 发布时行为 正确行为
LWG 2076 C++11 重载 ( 4 ) 有条件地要求 Key 可被 拷贝插入 * this 不作要求
LWG 2193 C++11 默认构造函数为显式 改为非显式

参见

为容器赋值
(公开成员函数)