内容简介:看到一个介绍 C++17 的系列博文(本篇是系列译文的最后一篇(译文总数不到十来篇)~C++11 中已经包含了8个关联容器,C++17 改进了这些容器的接口方法,现在你可以更加方便的向容器中插入元素,合并或者移动一个容器的元素至另一个"
看到一个介绍 C++17 的系列博文( 原文 ),有十来篇的样子,觉得挺好,看看有时间能不能都简单翻译一下,这是第八篇~
本篇是系列译文的最后一篇(译文总数不到十来篇)~
C++11 中已经包含了8个关联容器,C++17 改进了这些容器的接口方法,现在你可以更加方便的向容器中插入元素,合并或者移动一个容器的元素至另一个" 相似 "容器中,并且新标准还统一了关联容器和顺序容器的访问方式.
在我深入讲解细节之前,让我先来回答一下之前的一个问题:什么是"相似"容器?
目前标准库包含8个关联容器:
所谓的相似容器,其实就是所含元素的数据结构相同并且 数据类型也相同的容器.std::set 和 std::multiset 的元素便拥有相同的数据结构, std::unordered_set 和 std::unordered_multiset, std::map 和 std::multimap, 以及 std::unordered_map 和 std::unordered_multimap, 这几个容器对包含的元素也拥有相同的数据结构.
当然,上面的说明还是比较简略的,更多的细节我在之前的 文章 中已经做过介绍,有兴趣的朋友可以看看.
现在让我们来看些全新的东西.
The improved interface of the associative containers
下面的代码示例较详尽的展示了改进的容器接口.
#include <iostream> #include <map> #include <string> #include <utility> using namespace std::literals; // 1 template <typename Cont> void printContainer(const Cont& cont, const std::string& mess) { // 2 std::cout << mess; for (const auto& pa : cont) { std::cout << "(" << pa.first << ": " << pa.second << ") "; } std::cout << std::endl; } int main() { std::map<int, std::string> ordMap{ {1, "a"s}, {2, "b"} }; // 3 ordMap.try_emplace(3, 3, 'C'); ordMap.try_emplace(3, 3, 'c'); printContainer(ordMap, "try_emplace: "); std::cout << std::endl; std::map<int, std::string> ordMap2{ {3, std::string(3, 'C')}, // 4 {4, std::string(3, 'D')} }; ordMap2.insert_or_assign(5, std::string(3, 'e')); ordMap2.insert_or_assign(5, std::string(3, 'E')); printContainer(ordMap2, "insert_or_assign: "); // 5 std::cout << std::endl; ordMap.merge(ordMap2); // 6 std::cout << "ordMap.merge(ordMap2)" << std::endl; printContainer(ordMap, " ordMap: "); printContainer(ordMap2, " ordMap2: "); std::cout << std::endl; std::cout << "extract and insert: " << std::endl; std::multimap<int, std::string> multiMap{ {2017, std::string(3, 'F')} }; auto nodeHandle = multiMap.extract(2017); // 7 nodeHandle.key() = 6; ordMap.insert(std::move(nodeHandle)); printContainer(ordMap, " ordMap: "); printContainer(multiMap, " multiMap: "); return 0; }
代码示例中我使用了 std::map, 因为多数情况下他都是我们使用关联容器的第一选择.另外,如果你需要存储大量元素并且保证访问效率,你就可以试试 std::unordered_map.在我之前的 文章 中,我对这两个容器的访问效率做了一些比较.
代码 (2) 处我编写了 printContainer 函数用来方便的输出关联容器的元素(可以附加一个消息标题),同样是为了方便,我在 (1) 处引入了命名空间 std::literals,这样我就可以使用 C++ string 中新的内建字面量(literal)了.代码 (3) 中定义的键值对 {1, "a"s} 便是 string 字面量的一个应用: "a"s 是 C++14 引入的 string 字面量定义方式,你只需要在 C 风格字符串后面添加一个 s 字符便可获得一个 C++ string(字面量).
现在,我要开始详细解释示例程序的代码了,为了理解方便,让我们先看下程序的输出:
新标准中增加了两种向关联容器中添加元素的方法: try_emplace 和 insert_or_assign.代码 (3) 处的 ordMap.try_emplace(3, 3, ‘C’) 尝试向 ordMap 添加一个元素,其中第一个参数 3 是元素的键, 后面的两个参数 3 和 ‘C’ 则直接用于调用元素值(这里是std::string)的构造函数.之所以这个方法以try为前缀命名,是因为如果对应的元素键已经存在,该方法便不会执行实际的添加操作.代码 (4) 处的 insert_or_assign 方法则与 try_emplace 不同,如果对应的元素键已经存在,他会将新的元素值赋值给已经存在的元素键(建立新的键值对映射).
C++17 中,你还可以合并关联容器.代码 (6) 处的 ordMap.merge(ordMap2) 将 ordMap2 合并入了 ordMap 中.这个过程的正式名称叫"拼接(splice)",以上面代码为例,拼接的过程就是从 ordMap2 中抽取(extract)每一个键值对并插入 ordMap 中,如果 ordMap 中已经存在相同的元素键,则不会执行插入操作.整个过程不会发生键值对的 copy 或者 move 操作,所以拼接之前指向键值对的指针(或者引用)仍然保持有效.你可以在相似的关联容器间执行合并操作,而所谓的相似容器,正如之前所说,就是容器所包含的元素拥有相同的数据结构和相同的数据类型.
代码 (7) 处继续进行容器的抽取和插入操作.新标准中的关联容器都有一个新的子类型:node_type,代码 (6) 中的容器合并操作内部就是通过使用 node_type 来完成的.你甚至可以使用 node_type 来改变一个键值对的键:代码 (7) 处的 auto nodeHandle multiMap.extract(2017) 从 std::multimap<int, std::string> 中抽取了键为 2017 的节点(node_type),接下来的代码 nodeHandle.key() = 6 将节点的键改为了 6, 然后使用 ordMap.insert(std::move(nodeHandle)) 将节点插入到了 ordMap 中,这里我必须使用 move 的方式来插入提取的节点,因为 node_type 并不支持拷贝.
当然,你也可以更改抽取节点的键后插入回同一个关联容器中(A),或者直接不做任何更改(B).除了更改键,你也可以更改节点的值©.
auto nodeHandle = multiMap.extract(2017); // A nodeHandle.key() = 6; multiMap.insert(std::move(nodeHandle)); auto nodeHandle = multiMap.extract(2017); // B ordMap.insert(std::move(nodeHandle)); auto nodeHandle = multiMap.extract(2017); // C nodeHandle.mapped() = std::string("ZZZ"); ordMap.insert(std::move(nodeHandle));
C++17 中引入了3个全局函数用以统一的访问容器.
Uniform container access
这3个函数分别是 std::size, std::empty, 和 std::data.
- std::size: 返回一个 STL 容器,或者一个 C++ string, 或者一个 C 数组的大小(size).
- std::empty: 返回一个 STL 容器,或者一个 C++ string, 或者一个 C 数组是否为空.
- std::data: 返回容器所包含元素的内存块指针.使用前提是容器必须支持 data() 方法(标准库中的 std::vector, std::string 和 std::array 支持该方法).
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 容器编排工具 Kubernetes 1.9.9 发布,改进兼容性
- Servlet 容器 Jetty 9.4.10 发布,大量错误修复和改进
- 容器平台 OpenShift 3.9 正式发布,改进安全性和可用性
- FreeBSD 13.0-RC1 发布:改进 TCP 性能、修复和改进 SCTP
- Lanai-UI 改进后发布,AdminLTE 改进后的脚手架
- 敏捷开发的持续改进
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
正则表达式在线测试
正则表达式在线测试
HEX HSV 转换工具
HEX HSV 互换工具