set容器

news/发布时间2024/5/17 10:15:07

set 容器定义于<set>头文件,并位于 std 命名空间中。因此如果想在程序中使用 set 容器,该程序代码应先包含如下语句:

#include <set>using namespace std;

set 容器的类模板定义如下:

template < class T,                        // 键 key 和值 value 的类型class Compare = less<T>,        // 指定 set 容器内部的排序规则class Alloc = allocator<T>      // 指定分配器对象的类型> class set;

注意,由于 set 容器存储的各个键值对,其键和值完全相同,也就意味着它们的类型相同,因此 set 容器类模板的定义中,仅有第 1 个参数用于设定存储数据的类型。

1. set容器的创建

调用默认构造函数,创建空的 set 容器。比如:

std::set<std::string> myset;

set 类模板还支持在创建 set 容器的同时,对其进行初始化。例如:

std::set<std::int> myset{1, 2, 3, 4};

set 类模板中还提供了拷贝(复制)构造函数,可以实现在创建新 set 容器的同时,将已有 set 容器中存储的所有元素全部复制到新 set 容器中:

std::set<std::string> copyset(myset);
// 等同于
std::set<std::string> copyset = myset

该行代码在创建 copyset 容器的基础上,还会将 myset 容器中存储的所有元素,全部复制给 copyset 容器一份。

C++ 11 标准还为 set 类模板新增了移动构造函数,其功能是实现创建新 set 容器的同时,利用临时的 set 容器为其初始化。比如:

set<string> retSet() {std::set<std::string> myset{1, 2, 3};return myset;
}
std::set<std::string> copyset(retSet());
//或者
std::set<std::string> copyset = retSet();

注意:由于 retSet() 函数的返回值是一个临时 set 容器,因此在初始化 copyset 容器时,其内部调用的是 set 类模板中的移动构造函数,而非拷贝构造函数。

set 类模板还支持取已有 set 容器中的部分元素,来初始化新 set 容器。例如:

std::set<std::string> myset{1, 2, 3, 4};
std::set<std::string> copyset(++myset.begin(), myset.end());

以上几种方式创建的 set 容器,都采用了默认的std::less<T>规则。其实,借助 set 类模板定义中第 2 个参数,我们完全可以手动修改 set 容器中的排序规则。比如:

std::set<std::string,std::greater<string> > myset{1, 2, 3, 4};

2. set成员函数

成员方法 功能
begin() 返回指向容器中第一个(注意,是已排好序的第一个)元素的双向迭代器。如果 set 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
end() 返回指向容器最后一个元素(注意,是已排好序的最后一个)所在位置后一个位置的双向迭代器,通常和 begin() 结合使用。如果 set 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
rbegin() 返回指向最后一个(注意,是已排好序的最后一个)元素的反向双向迭代器。如果 set 容器用 const 限定,则该方法返回的是 const 类型的反向双向迭代器。
rend() 返回指向第一个(注意,是已排好序的第一个)元素所在位置前一个位置的反向双向迭代器。如果 set 容器用 const 限定,则该方法返回的是 const 类型的反向双向迭代器。
cbegin() 和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的元素值。
cend() 和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的元素值。
crbegin() 和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的元素值。
crend() 和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的元素值。
find(val) 在 set 容器中查找值为 val 的元素,如果成功找到,则返回指向该元素的双向迭代器;反之,则返回和 end() 方法一样的迭代器。另外,如果 set 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
lower_bound(val) 返回一个指向当前 set 容器中第一个小于或等于 val 的元素的双向迭代器。如果 set 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
upper_bound(val) 返回一个指向当前 set 容器中第一个大于 val 的元素的迭代器。如果 set 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
equal_range(val) 该方法返回一个 pair 对象(包含 2 个双向迭代器),其中 pair.first 和 lower_bound() 方法的返回值等价,pair.second 和 upper_bound() 方法的返回值等价。也就是说,该方法将返回一个范围,该范围中包含的值为 val 的元素(set 容器中各个元素是唯一的,因此该范围最多包含一个元素)。
empty() 若容器为空,则返回 true;否则 false。
size() 返回当前 set 容器中存有元素的个数。
max_size() 返回 set 容器所能容纳元素的最大个数,不同的操作系统,其返回值亦不相同。
insert() 向 set 容器中插入元素。
erase() 删除 set 容器中存储的元素。
swap() 交换 2 个 set 容器中存储的所有元素。这意味着,操作的 2 个 set 容器的类型必须相同。
clear() 清空 set 容器中所有的元素,即令 set 容器的 size() 为 0。
emplace() 在当前 set 容器中的指定位置直接构造新元素。其效果和 insert() 一样,但效率更高。
emplace_hint() 在本质上和 emplace() 在 set 容器中构造新元素的方式是一样的,不同之处在于,使用者必须为该方法提供一个指示新元素生成位置的迭代器,并作为该方法的第一个参数。
count(val) 在当前 set 容器中,查找值为 val 的元素的个数,并返回。注意,由于 set 容器中各元素的值是唯一的,因此该函数的返回值最大为 1。

3. insert操作

3.1 方式一

只要给定目标元素的值,insert() 方法即可将该元素添加到 set 容器中,其语法格式如下:

// 普通引用方式传参
pair<iterator,bool> insert (const value_type& val);
// 右值引用方式传参
pair<iterator,bool> insert (value_type&& val);

其中,val 表示要添加的新元素,该方法的返回值为 pair 类型。

可以看到,以上 2 种语法格式的 insert() 方法,返回的都是 pair 类型的值,其包含 2 个数据,一个迭代器和一个 bool 值:

  • 当向 set 容器添加元素成功时,该迭代器指向 set 容器新添加的元素,bool 类型的值为 true;

  • 如果添加失败,即证明原 set 容器中已存有相同的元素,此时返回的迭代器就指向容器中相同的此元素,同时 bool 类型的值为 false。

#include <iostream>
#include <set>
#include <string>using namespace std;int main()
{// 创建并初始化set容器std::set<std::string> myset;// 准备接受 insert() 的返回值pair<set<string>::iterator, bool> retpair;// 采用普通引用传值方式string str = "http://c.biancheng.net/stl/";retpair = myset.insert(str);cout << "iter->" << *(retpair.first) << " " << "bool = " << retpair.second << endl;// 采用右值引用传值方式retpair = myset.insert("http://c.biancheng.net/python/");cout << "iter->" << *(retpair.first) << " " << "bool = " << retpair.second << endl;return 0;
}

3.2 方式二

insert() 还可以指定将新元素插入到 set 容器中的具体位置,其语法格式如下:

// 以普通引用的方式传递 val 值
iterator insert (const_iterator position, const value_type& val);
// 以右值引用的方式传递 val 值
iterator insert (const_iterator position, value_type&& val);
#include <iostream>
#include <set>
#include <string>using namespace std;int main()
{// 创建并初始化set容器std::set<std::string> myset;// 准备接受 insert() 的返回值set<string>::iterator iter;// 采用普通引用传值方式string str = "http://c.biancheng.net/stl/";iter = myset.insert(myset.begin(),str);cout << "myset size =" << myset.size() << endl;// 采用右值引用传值方式iter = myset.insert(myset.end(),"http://c.biancheng.net/python/");cout << "myset size =" << myset.size() << endl;return 0;

注意:使用 insert() 方法将目标元素插入到 set 容器指定位置后,如果该元素破坏了容器内部的有序状态,set 容器还会自行对新元素的位置做进一步调整。也就是说,insert() 方法中指定新元素插入的位置,并不一定就是该元素最终所处的位置。

3.3 方式三

insert() 方法支持向当前 set 容器中插入其它 set 容器指定区域内的所有元素,只要这 2 个 set 容器存储的元素类型相同即可。

template <class InputIterator>
void insert (InputIterator first, InputIterator last);

其中 first 和 last 都是迭代器,它们的组合 [first,last) 可以表示另一 set 容器中的一块区域,该区域包括 first 迭代器指向的元素,但不包含 last 迭代器指向的元素。

#include <iostream>
#include <set>
#include <string>using namespace std;int main()
{//创建并初始化set容器std::set<std::string> myset{ "http://c.biancheng.net/stl/","http://c.biancheng.net/python/","http://c.biancheng.net/java/" };// 创建一个同类型的空 set 容器std::set<std::string> otherset;// 利用 myset 初始化 othersetotherset.insert(++myset.begin(), myset.end());// 输出 otherset 容器中的元素for (auto iter = otherset.begin(); iter != otherset.end(); ++iter) {cout << *iter << endl;}return 0;
}

3.4 emplace操作

template <class... Args>
pair<iterator,bool> emplace (Args&&... args);

另外,该方法的返回值类型为 pair 类型,其包含 2 个元素,一个迭代器和一个 bool 值:

  • 当该方法将目标元素成功添加到 set 容器中时,其返回的迭代器指向新插入的元素,同时 bool 值为 true;

  • 当添加失败时,则表明原 set 容器中已存在相同值的元素,此时返回的迭代器指向容器中具有相同键的这个元素,同时 bool 值为false;

#include <iostream>
#include <set>
#include <string>using namespace std;int main()
{// 创建并初始化 set 容器std::set<string>myset;// 向 myset 容器中添加元素pair<set<string, string>::iterator, bool> ret = myset.emplace("http://c.biancheng.net/stl/");cout << "myset size = " << myset.size() << endl;cout << "ret.iter = <" << *(ret.first) << ", " << ret.second << ">" << endl;return 0;
}

3.5  emplace_hint操作

emplace() 方法相比,有以下 2 点不同:

  • 该方法需要额外传入一个迭代器,用来指明新元素添加到 set 容器的具体位置(新元素会添加到该迭代器指向元素的前面);

  • 返回值是一个迭代器,而不再是 pair 对象。当成功添加元素时,返回的迭代器指向新添加的元素;反之,如果添加失败,则迭代器就指向 set 容器和要添加元素的值相同的元素。

emplace() 、emplace_hint() 比insert() 效率高的原因:

  • 使用 insert() 向 map / set 容器中插入键值对的过程是,先创建该键值对,然后再将该键值对复制或者移动到 map 容器中的指定位置;整个插入过程调用了 1 次类的构造函数,同时还调用了 2次移动构造函数。

  • 使用 emplace() 或 emplace_hint() 插入键值对的过程是,直接在 map 容器中的指定位置构造该键值对。

template <class... Args>
iterator emplace_hint (const_iterator position, Args&&... args);

4. erase操作

如果想删除 set 容器存储的元素,可以选择用 erase() 或者 clear() 成员方法。

set 类模板中,erase() 方法有 3 种语法格式,分别如下:

// 删除 set 容器中值为 val 的元素
size_type erase (const value_type& val);
// 删除 position 迭代器指向的元素
iterator  erase (const_iterator position);
// 删除 [first,last) 区间内的所有元素
iterator  erase (const_iterator first, const_iterator last);

其中,第 1 种格式的 erase() 方法,其返回值为一个整数,表示成功删除的元素个数;后 2 种格式的 erase() 方法,返回值都是迭代器,其指向的是 set 容器中删除元素之后的第一个元素如果要删除的元素就是 set 容器最后一个元素,则 erase() 方法返回的迭代器就指向新 set 容器中最后一个元素之后的位置(等价于 end() 方法返回的迭代器)。

如果需要删除 set 容器中存储的所有元素,可以使用 clear() 成员方法。该方法的语法格式如下:

void clear();

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ulsteruni.cn/article/74846821.html

如若内容造成侵权/违法违规/事实不符,请联系编程大学网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

docker下安装gitlab配置以及备份

安装 docker run --detach --publish 443:443 --publish 9980:80 --publish 9922:22 --name gitlab --restart always --volume /srv/gitlab/config:/etc/gitlab --volume /srv/gitlab/logs:/var/log/gitlab --volume /srv/gitlab/data:/var/opt/gitlab --shm-size 256m gitlab…

mysql添加数据报错

1452 - Cannot add or update a child row: a foreign key constraint fails (db_student_manager_web.s_student, CONSTRAINT student_clazz_id_foreign FOREIGN KEY (clazz_id) REFERENCES s_clazz (id))在mysql添加数据的时候报错,如上图所示 在chat上查询该错误,chat给出…

IEC104 从站/服务端模拟器 调试工具推荐

在开发调试过程中,一款合适的从站模拟器可以大大提高效率。下面推荐一款IEC104 从站/服务端模拟器。目录IEC104 从站/服务端模拟器 调试工具推荐主要功能软件截图 IEC104 从站/服务端模拟器 调试工具推荐 下载地址:http://www.redisant.cn/iec104server IEC 60870-5-104,通常…

MibBrowser工具测试服务器告警上报

在工具栏【tools】---》【Trap Receiver】选择与服务器直连网卡的IP地址及对应的端口号(确保自己的电脑可以正常和服务器通信)在BMC Trap位置配置自己电脑的IP地址,用于接收上报的告警信息点击【测试】查看已经正常收到服务器测试上报信息了。你也可以尝试拔盘和拔电源看看是…

Windows Server 2016 中文版、英文版下载 (updated Apr 2024)

Windows Server 2016 中文版、英文版下载 (updated Apr 2024)Windows Server 2016 中文版、英文版下载 (updated Apr 2024) Windows Server 2016 Version 1607,2024 年 4 月更新 请访问原文链接:Windows Server 2016 中文版、英文版下载 (updated Apr 2024),查看最新版。原创…

收集:本地运行Llama3

本地运行Llama3新方法#国外有网友火速分享了在本地(Windows、Linux、Mac)一键运行 Llama 3 的新方法~废话不多说,先看效果。【图1】在视频1倍速播放中,他用 OpenWebUI 在自己的 Macbook Pro M1 Max 64G 上成功运行了 Llama 3 。而且还添加了侧边栏展开收起。【图2】以上效果…