修改器
1、clear 清除内容 (公开成员函数)
std::set::clear
void clear(); (C++11 前)
void clear() noexcept; (C++11 起)
从容器擦除所有元素。此调用后 size() 返回零。
非法化任何指代所含元素的引用、指针或迭代器。任何尾后迭代器保持合法。
用例
std::set set1{'A', 'B', 'C', 'D', 'E'};
std::cout << "set1 size: " << set1.size() << std::endl;
set1.clear();
std::cout << "clear after set1 size: " << set1.size() << std::endl;
2、insert 插入元素或结点 (C++17 起)(公开成员函数)
插入元素到容器,若容器未含拥有等价关键的元素。
std::set::insert
1-2) 插入 value
。
1-2) 返回由指向被插入元素(或阻止插入的元素)的迭代器和若插入发生则设为 true 的 bool 值。
std::pair insert( const value_type& value ); (1)
std::pair insert( value_type&& value ); (2) (C++11 起)
3-4) 插入 value
到尽可能接近,正好前于(C++11 起) hint
的位置。
3-4) 返回指向被插入元素,或阻止插入的元素的迭代器。
(3)
iterator insert( iterator hint, const value_type& value ); (C++11 前)
iterator insert( const_iterator hint, const value_type& value ); (C++11 起)
(4)
iterator insert( const_iterator hint, value_type&& value ); (C++11 起)
5) 插入来自范围 [first, last)
的元素。 若范围中的多个元素拥有比较等价的关键,则插入哪个元素是未指定的
template< class InputIt >
void insert( InputIt first, InputIt last ); (5)
6) 插入来自 initializer_list ilist
的元素。 若范围中的多个元素拥有比较等价的关键,则插入哪个元素是未指定的
void insert( std::initializer_list ilist ); (6) (C++11 起)
hint |
|
||||
value | 要插入的元素值 | ||||
first, last | 要插入的元素范围 | ||||
ilist | 插入值来源的 initializer_list | ||||
nh | 兼容的结点把柄 | ||||
类型要求 | |||||
- InputIt 必须满足遗留输入迭代器 (LegacyInputIterator) 的要求。 |
1-4) 若任何操作抛异常,则插入无效果。
1-2) 与容器大小成对数, O(log(size()))
。
3-4) 若插入恰好发生在正好后于 hint 的位置,则为均摊常数,否则与容器大小成对数。(C++11 前)
3-4) 若插入恰好发生在正好先于 hint 的位置,则为均摊常数,否则与容器大小成对数。(C++11 起)
5-6) O(N*log(size() + N))
,其中 N 是要插入的元素数。
有提示插入 (3,4) 不返回 bool ,这是为了与顺序容器上的定位插入,如 std::vector::insert 签名兼容。这使得可以创建泛型插入器,例如 std::inserter 。检查有提示插入是否成功的一种方式是比较插入前后的 size() 。
重载 (5,6) 通常实现为循环,其中以 end() 为 hint 调用重载 (3) ;它们对后附最小元素大于 *this 中最大元素的有序序列(例如另一 set )优化
示例
std::set set1;
std::pair::iterator, bool> it = set1.insert('A');
std::cout << "insert 'A' " << (it.second ? "true" : "false") << std::endl;
it = set1.insert('A');
std::cout << "insert 'A' " << (it.second ? "true" : "false") << std::endl;
std::set::const_iterator itb = set1.cbegin();
std::set::const_iterator itp = set1.insert(itb, 'B');
std::cout << "insert 'B' : " << *itp << std::endl;
std::vector arr{'A', 'B', 'C', 'D', 'E'};
set1.insert(arr.begin(), arr.end());
printSet("range insert ", set1);
3、emplace (C++11) 原位构造元素 (公开成员函数)
std::set::emplace
template< class... Args >
std::pair emplace( Args&&... args ); (C++11 起)
若容器中无拥有该关键的元素,则插入以给定的 args
原位构造的新元素到容器。
细心地使用 emplace
允许在构造新元素的同时避免不必要的复制或移动操作。 准确地以与提供给 emplace
者相同的参数,通过 std::forward
没有迭代器或引用被非法化。
args | - | 要转发给元素构造函数的参数 |
返回由指向被插入元素,或若不发生插入则为既存元素的迭代器,和指代插入是否发生的 bool (若发生插入则为 true ,否则为 false )。
示例
std::set set1;
char ch = 'A';
while (ch != 'E')
{
set1.emplace(ch);
ch++;
}
printSet("emplace", set1);
4、emplace_hint 使用提示原位构造元素(公开成员函数)
插入新元素到容器中尽可能接近于恰在 hint
前的位置。原位构造元素,即不进行复制或移动操作。
以提供给函数的参数准确相同者,以 std::forward
没有迭代器或引用被非法化。
hint | - | 指向新元素将插入到其前的位置的迭代器 |
args | - | 转发给元素构造函数的参数 |
返回指向新插入元素的迭代器。
若因元素已存在而插入失败,则返回指向拥有等价关键的既存元素的迭代器。
若任何操作抛出异常,则此函数无效果(强异常保证)。
通常与容器大小成对数,但若新元素正好被插入到 hint
之前则为均摊常数。
示例
std::set set1;
char ch = 'A';
while (ch != 'C')
{
set1.emplace(ch);
ch++;
}
printSet("emplace", set1);
std::set::const_iterator it = set1.find('B');
set1.emplace_hint(it, 'D', );
printSet("emplace_hint", set1);
5、erase 擦除元素(公开成员函数
从容器移除指定的元素。
std::set::erase
1) 移除位于 pos
的元素。
void erase( iterator pos ); (C++11 前)
iterator erase( const_iterator pos ); (C++11 起)
iterator erase( iterator pos ); (C++17 起)
2) 移除范围 [first; last)
中的元素,它必须是 *this 中的合法范围。
void erase( iterator first, iterator last ); (C++11 前)
iterator erase( const_iterator first, const_iterator last ); (C++11 起)
3) 移除关键等于 key
的元素(若存在一个)。
size_type erase( const key_type& key ); (3)
指向被擦除元素的引用和迭代器被非法化。其他引用和迭代器不受影响。
迭代器 pos
必须合法且可解引用。从而 end() 迭代器(合法,但不可解引用)不能用作 pos
所用的值。
pos | - | 指向要移除的元素的迭代器 |
first, last | - | 要移除的元素范围 |
key | - | 要移除的元素关键值 |
1-2) 后随最后被移除的元素的迭代器。
3) 被移除的元素数。
1,2) (无)
3) 任何 Compare
对象所抛的异常
给定 set
的实例 c
:
1) 均摊常数
2) log(c.size()) + std::distance(first, last)
3) log(c.size()) + c.count(k)
示例
std::set set1{'A', 'B', 'C', 'D', 'E'};
printSet("erase before", set1);
std::set::const_iterator it = set1.find('C');
set1.erase(it);
printSet("erase(it)", set1);
set1.erase(set1.find('A'), set1.find('D'));
printSet("erase() range", set1);
set1.erase('D');
printSet("erase() value", set1);
6、swap 交换元素(公开成员函数)
将内容与 other
的交换。不在单个元素上调用任何移动、复制或交换操作。
std::set::swap
void swap( set& other ); (C++17 前)
void swap( set& other ) noexcept(/* see below */); (C++17 起)
将内容与 other
的交换。不在单个元素上调用任何移动、复制或交换操作。
所有迭代器和引用保持合法。尾后迭代器被非法化。
Pred
对象必须可交换 (Swappable) ,并用非成员 swap
的非限定调用交换它们。
若 std::allocator_traits |
(C++11 起) |
other | - | 要与之交换内容的容器 |
(无)
任何 |
(C++17 前) |
noexcept 规定: noexcept(std::allocator_traits |
(C++17 起) |
常数。
示例
std::set set1{'A', 'B', 'C'};
std::set set2{'D', 'E'};
std::cout << "swap() before" << std::endl;
printSet("set1", set1);
printSet("set2", set2);
set1.swap(set2);
std::cout << "swap() after" << std::endl;
printSet("set1", set1);
printSet("set2", set2);
template
void merge(std::set& source); (1) (C++17 起)
template
void merge(std::set&& source); (2) (C++17 起)
template
void merge(std::multiset& source); (3) (C++17 起)
template
void merge(std::multiset&& source); (4) (C++17 起)
试图释出(“接合”) source
中每个元素,并用 *this
的比较对象插入到 *this
。 若 *this
中有元素,其关键等价于来自 source
中元素的关键,则不从 source
释出该元素。 不复制或移动元素,只会重指向容器结点的内部指针。指向被转移元素的所有指针和引用保持合法,但现在指代到 *this
中而非到 source
中。
若 get_allocator() != source.get_allocator() 则行为未定义。
source | - | 传递结点来源的兼容容器 |
(无)
不抛异常,除非比较抛出。
N*log(size()+N)) ,其中 N 为 source.size()
代码汇总
#include
#include
#include
#include
#include
#include
#include
// 打印容器元素
template >
void printSet(const std::string &name, const std::set &setP)
{
std::cout << name << " : ";
for (auto s : setP)
{
std::cout << s << ' ';
}
std::cout << std::endl;
}
// 自定义比较
struct myGreaterCompare
{
myGreaterCompare() {}
template < typename T>
bool operator()(const T &a, const T &b)const
{
return a > b;
}
};
void constructor()
{
std::cout << "constructor start " << std::endl;
// c++11 初始化容器列表语法:
// 默认升序
std::set set1{'A', 'B', 'C', 'D', 'E'};
printSet("default ", set1);
// 递增
std::set> set2{'A', 'B', 'C', 'D', 'E'};
printSet("std::less<> ", set2);
// 递减
std::set> set3{'A', 'B', 'C', 'D', 'E'};
printSet("std::greater<>", set3);
// 自定义比较函数
std::set set4{'A', 'B', 'C', 'D', 'E'};
printSet("myGreaterCompare", set4);
// 拷贝构造函数, set 必须同类型,包括比较
std::set> set5(set3);
printSet("copy constructor", set5);
// 赋值构造函数, set 必须同类型,包括比较
std::set> set6 = set2;
printSet("assignment constructor", set6);
// 范围构造
std::set set7(set6.begin(), set6.end());
printSet("range constructor", set7);
std::cout << "constructor end " << std::endl << std::endl;
}
void capacity()
{
std::cout << "capacity start " << std::endl;
// 检查容器是否无元素
std::set set1;
std::cout << "set1 is empty ? : " << (set1.empty() ? "empty" : "no empty") << std::endl;
set1.insert('A');
std::cout << "set1 is empty ? : " << (set1.empty() ? "empty" : "no empty") << std::endl;
// 返回容器中的元素数
std::set set2;
std::cout << "set2 size : " << set2.size() << std::endl;
set2 = std::set {'A', 'B', 'C', 'D', 'E'};
std::cout << "set2 size : " << set2.size() << std::endl;
// 返回根据系统或库实现限制的容器可保有的元素最大数量
std::set set3;
std::cout << "std::set max_size() : " << set3.max_size() << std::endl;
std::set set4;
std::cout << "std::set max_size() : " << set4.max_size() << std::endl;
std::set set5;
std::cout << "std::set max_size() : " << set5.max_size() << std::endl;
std::set set6;
std::cout << "std::set max_size() : " << set6.max_size() << std::endl;
std::cout << "capacity end " << std::endl << std::endl;
}
void compareFunc()
{
// 返回比较值的函数对象
std::cout << "observer start " << std::endl;
std::set set1;
std::cout << "std::set key_comp() : "
<< typeid(set1.key_comp()).name() << std::endl;
// 比较'A','B'大小,'A'比'B'小
std::cout << "std::less<> compare('A','B') : " <<
(set1.key_comp()('A', 'B') ? "true" : "false") << std::endl;
std::set> set2;
std::cout << "std::set> key_comp() : "
<< typeid(set2.key_comp()).name() << std::endl;
// 比较'A','B'大小,'A'比'B'大
std::cout << "std::greater<> compare('A','B') : " <<
(set1.key_comp()('A', 'B') ? "true" : "false") << std::endl;
std::set set3;
std::cout << "std::set key_comp() : "
<< typeid(set3.key_comp()).name() << std::endl;
std::cout << "observer end " << std::endl << std::endl;
}
void clearTest()
{
std::cout << "clearTest start " << std::endl;
std::set set1{'A', 'B', 'C', 'D', 'E'};
std::cout << "set1 size: " << set1.size() << std::endl;
set1.clear();
std::cout << "clear after set1 size: " << set1.size() << std::endl;
std::cout << "clearTest end " << std::endl << std::endl;
}
void insertTest()
{
std::cout << "insertTest start " << std::endl;
std::set set1;
std::pair::iterator, bool> it = set1.insert('A');
std::cout << "insert 'A' " << (it.second ? "true" : "false") << std::endl;
it = set1.insert('A');
std::cout << "insert 'A' " << (it.second ? "true" : "false") << std::endl;
std::set::const_iterator itb = set1.cbegin();
std::set::const_iterator itp = set1.insert(itb, 'B');
std::cout << "insert 'B' : " << *itp << std::endl;
std::vector arr{'A', 'B', 'C', 'D', 'E'};
set1.insert(arr.begin(), arr.end());
printSet("range insert ", set1);
std::cout << "insertTest end " << std::endl << std::endl;
}
void emplaceTest()
{
std::cout << "emplaceTest start " << std::endl;
std::set set1;
char ch = 'A';
while (ch != 'C')
{
set1.emplace(ch);
ch++;
}
printSet("emplace", set1);
std::set::const_iterator it = set1.find('B');
set1.emplace_hint(it, 'D');
printSet("emplace_hint", set1);
std::cout << "emplaceTest end " << std::endl << std::endl;
}
void eraseTest()
{
std::cout << "eraseTest start " << std::endl;
std::set set1{'A', 'B', 'C', 'D', 'E'};
printSet("erase before", set1);
std::set::const_iterator it = set1.find('C');
set1.erase(it);
printSet("erase(it)", set1);
set1.erase(set1.find('A'), set1.find('D'));
printSet("erase() range", set1);
set1.erase('D');
printSet("erase() value", set1);
std::cout << "eraseTest end " << std::endl << std::endl;
}
void swapTest()
{
std::cout << "swapTest start " << std::endl;
std::set set1{'A', 'B', 'C'};
std::set set2{'D', 'E'};
std::cout << "swap() before" << std::endl;
printSet("set1", set1);
printSet("set2", set2);
set1.swap(set2);
std::cout << "swap() after" << std::endl;
printSet("set1", set1);
printSet("set2", set2);
std::cout << "swapTest end " << std::endl << std::endl;
}
int main()
{
// constructor();
// capacity();
// compareFunc();
clearTest();
insertTest();
emplaceTest();
eraseTest();
swapTest();
return 0;
}