C++23 新增扁平化关联容器详解

文章目录

    • 一、引言
      • 已有关联容器回顾
      • 新容器的引入原因
    • 二、`std::flat_set`
      • 定义与特性
      • 代码示例
      • 适用场景
    • 三、`std::flat_multiset`
      • 定义与特性
      • 代码示例
      • 适用场景
    • 四、`std::flat_map`
      • 定义与特性
      • 代码示例
      • 适用场景
    • 五、`std::flat_multimap`
      • 定义与特性
      • 代码示例
      • 适用场景
    • 六、与其他容器的比较
      • 与 `std::set` 和 `std::multiset` 的比较
      • 与 `std::map` 和 `std::multimap` 的比较
    • 七、总结

一、引言

在 C++23 标准中,引入了四个新的关联容器:std::flat_setstd::flat_multisetstd::flat_mapstd::flat_multimap。这些容器是对底层有序随机访问容器进行包装的容器适配器,旨在为开发者提供在某些场景下比传统关联容器更高效的选择。在介绍这四个新容器之前,我们先回顾一下 C++ 中已有的关联容器。

已有关联容器回顾

  • C++98:引入了 std::mapstd::setstd::multimapstd::multiset,这些容器基于红黑树实现,元素按键有序存储,插入、删除和查找操作的时间复杂度为 O ( l o g n ) O(log n) O(logn)
  • C++11:引入了 std::unordered_mapstd::unordered_setstd::unordered_multimapstd::unordered_multiset,这些容器基于哈希表实现,元素无序存储,平均情况下插入、删除和查找操作的时间复杂度为 O ( 1 ) O(1) O(1)

新容器的引入原因

新容器的引入主要是为了在内存消耗和性能方面提供不同的选择。与传统的关联容器相比,平铺容器在某些场景下具有更好的缓存局部性,从而提高性能。

二、std::flat_set

定义与特性

std::flat_set 是一个类似于 std::set 的容器,但它使用扁平化存储的唯一键集合。它的底层实现使用排序的连续存储(通常是 std::vector 或类似结构),而不是树结构。这使得元素在内存中是连续存储的,具有以下特点:

  • 查找速度快:查找操作使用二分查找,时间复杂度为 O ( l o g n ) O(log n) O(logn)。由于内存连续,缓存命中率高,总体查找速度比 std::set 快。
  • 插入和删除较慢:插入和删除操作通常需要对数组中的元素进行整体移动,尤其在不支持移动构造时,时间复杂度为 O ( n ) O(n) O(n)
  • 迭代速度快:由于内存局部性,迭代速度比 std::set 快。
  • 内存占用小:相对于平衡二叉树,减少了节点指针的维护,从而节省了内存空间。

代码示例

#include <flat_set>
#include <iostream>int main() {std::flat_set<int> primes{2, 3, 5, 7, 11};// 插入元素primes.insert(13);// 检查存在性if (primes.contains(7)) {std::cout << "7 is a prime number" << std::endl;}// 范围查询auto [begin, end] = primes.equal_range(5);for (auto it = begin; it != end; ++it) {std::cout << *it << " ";}std::cout << std::endl;return 0;
}

适用场景

  • 需要频繁查找但较少插入/删除:由于查找速度快,插入和删除操作相对较慢,适合用于需要频繁查找元素的场景。
  • 需要快速迭代:内存连续的特性使得迭代速度快,适合需要快速遍历元素的场景。
  • 内存受限环境:内存占用小的特点使得它在内存受限的环境中更具优势。

三、std::flat_multiset

定义与特性

std::flat_multiset 类似于 std::flat_set,但允许存储多个具有相同键的元素。它同样使用排序的连续存储,具有与 std::flat_set 类似的性能特点:

  • 查找速度快:查找操作使用二分查找,时间复杂度为 O ( l o g n ) O(log n) O(logn)
  • 插入和删除较慢:插入和删除操作通常需要对数组中的元素进行整体移动,时间复杂度为 O ( n ) O(n) O(n)
  • 迭代速度快:由于内存局部性,迭代速度快。
  • 内存占用小:相对于平衡二叉树,减少了节点指针的维护,从而节省了内存空间。

代码示例

#include <flat_set>
#include <iostream>int main() {std::flat_multiset<int> numbers{1, 2, 2, 3, 3, 3};// 插入元素numbers.insert(4);// 查找元素auto range = numbers.equal_range(2);for (auto it = range.first; it != range.second; ++it) {std::cout << *it << " ";}std::cout << std::endl;return 0;
}

适用场景

  • 需要存储重复元素且需要快速查找:与 std::flat_set 类似,但允许存储重复元素,适合需要存储重复元素且需要快速查找的场景。
  • 需要快速迭代:内存连续的特性使得迭代速度快,适合需要快速遍历元素的场景。
  • 内存受限环境:内存占用小的特点使得它在内存受限的环境中更具优势。

四、std::flat_map

定义与特性

std::flat_map 是一个类似于 std::map 的容器,但它使用扁平化存储的键值对容器。它的底层实现使用两个有序数组,一个存储键,另一个存储值,具有以下特点:

  • 查找速度快:查找操作使用二分查找,时间复杂度为 O ( l o g n ) O(log n) O(logn)。由于内存连续,缓存命中率高,总体查找速度比 std::map 快。
  • 插入和删除较慢:插入和删除操作通常需要对数组中的元素进行整体移动,尤其在不支持移动构造时,时间复杂度为 O ( n ) O(n) O(n)
  • 迭代速度快:由于内存局部性,迭代速度比 std::map 快。
  • 内存占用小:相对于平衡二叉树,减少了节点指针的维护,从而节省了内存空间。
  • 使用随机访问迭代器:与 std::map 使用双向迭代器不同,std::flat_map 使用随机访问迭代器。
  • 迭代器不稳定:插入和删除元素时迭代器会失效。
  • 无法存储不可复制和不可移动的值类型:由于需要对元素进行移动和复制,无法存储不可复制和不可移动的值类型。
  • 异常安全性弱:在删除和插入时移动值可能会抛出异常。

代码示例

#include <flat_map>
#include <iostream>
#include <string>int main() {std::flat_map<std::string, int> ages{{"Alice", 30},{"Bob", 25},{"Charlie", 35}};// 插入元素(可能触发排序和移动)ages.insert({"David", 28});// 查找元素if (auto it = ages.find("Alice"); it != ages.end()) {std::cout << "Alice is " << it->second << " years old" << std::endl;}// 迭代for (const auto& [name, age] : ages) {std::cout << name << ": " << age << std::endl;}return 0;
}

适用场景

  • 需要频繁查找但较少插入/删除:由于查找速度快,插入和删除操作相对较慢,适合用于需要频繁查找元素的场景。
  • 需要快速迭代:内存连续的特性使得迭代速度快,适合需要快速遍历元素的场景。
  • 内存受限环境:内存占用小的特点使得它在内存受限的环境中更具优势。

五、std::flat_multimap

定义与特性

std::flat_multimap 类似于 std::flat_map,但允许存储多个具有相同键的键值对。它同样使用排序的连续存储,具有与 std::flat_map 类似的性能特点:

  • 查找速度快:查找操作使用二分查找,时间复杂度为 O ( l o g n ) O(log n) O(logn)
  • 插入和删除较慢:插入和删除操作通常需要对数组中的元素进行整体移动,时间复杂度为 O ( n ) O(n) O(n)
  • 迭代速度快:由于内存局部性,迭代速度快。
  • 内存占用小:相对于平衡二叉树,减少了节点指针的维护,从而节省了内存空间。

代码示例

#include <flat_map>
#include <iostream>
#include <string>int main() {std::flat_multimap<std::string, int> scores{{"Alice", 80},{"Bob", 90},{"Alice", 85}};// 插入元素scores.insert({"Charlie", 75});// 查找元素auto range = scores.equal_range("Alice");for (auto it = range.first; it != range.second; ++it) {std::cout << it->first << ": " << it->second << std::endl;}return 0;
}

适用场景

  • 需要存储重复键的键值对且需要快速查找:与 std::flat_map 类似,但允许存储重复键的键值对,适合需要存储重复键的键值对且需要快速查找的场景。
  • 需要快速迭代:内存连续的特性使得迭代速度快,适合需要快速遍历元素的场景。
  • 内存受限环境:内存占用小的特点使得它在内存受限的环境中更具优势。

六、与其他容器的比较

std::setstd::multiset 的比较

特性std::set/std::multisetstd::flat_set/std::flat_multiset
底层实现红黑树排序的连续存储(通常是 std::vector
查找速度 O ( l o g n ) O(log n) O(logn) O ( l o g n ) O(log n) O(logn),但缓存友好,总体速度更快
插入和删除速度 O ( l o g n ) O(log n) O(logn) O ( n ) O(n) O(n)
迭代速度较慢较快
内存占用较大较小
迭代器稳定性稳定不稳定

std::mapstd::multimap 的比较

特性std::map/std::multimapstd::flat_map/std::flat_multimap
底层实现红黑树排序的连续存储(通常是 std::vector
查找速度 O ( l o g n ) O(log n) O(logn) O ( l o g n ) O(log n) O(logn),但缓存友好,总体速度更快
插入和删除速度 O ( l o g n ) O(log n) O(logn) O ( n ) O(n) O(n)
迭代速度较慢较快
内存占用较大较小
迭代器稳定性稳定不稳定
迭代器类型双向迭代器随机访问迭代器

七、总结

C++23 引入的 std::flat_setstd::flat_multisetstd::flat_mapstd::flat_multimap 为开发者提供了在某些场景下比传统关联容器更高效的选择。这些容器在查找和迭代操作上具有更好的性能,同时内存占用更小。然而,它们的插入和删除操作相对较慢,迭代器也不稳定。因此,在选择使用这些容器时,需要根据具体的应用场景进行权衡。如果需要频繁进行查找和迭代操作,且插入和删除操作较少,那么这些平铺容器是一个不错的选择。

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

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

相关文章

使用zap,对web应用/API接口 做安全检测

https://www.zaproxy.org/getting-started/ 检测方法 docker pull ghcr.io/zaproxy/zaproxy:stable# 执行baseline测试 docker run -t ghcr.io/zaproxy/zaproxy:stable zap-baseline.py \ -t https://baseline.yeshen.org# 执行api测试 docker run -t ghcr.io/zaproxy/zaproxy…

Qt—模态与非模态对话框

Qt—模态与非模态对话框 核心概念 ​模态对话框​​&#xff1a;强制用户优先处理当前窗口&#xff0c;阻塞指定范围的用户交互。​非模态对话框​​&#xff1a;允许用户自由切换窗口&#xff0c;无交互限制。 一、模态对话框类型与行为 1. 应用级模态&#xff08;Applica…

Axure高保真CRM客户关系管理系统原型

一套出色的CRM&#xff08;客户关系管理&#xff09;系统&#xff0c;无疑是企业管理者掌控客户动态、提升销售业绩的得力助手。今天&#xff0c;就为大家介绍一款精心打造的Axure高保真CRM客户关系管理系统原型模板&#xff0c;助你轻松开启高效客户管理之旅。 这款CRM原型模…

【羊圈——状压 + DP / 记忆化搜索DP】

题目 一般DP代码&#xff08;注意&#xff0c;这里只能向外推(起始状态是f(1,0)&#xff0c;不能向内推&#xff08;不然会导致之前的羊圈被割裂&#xff09;&#xff09; #include <bits/stdc.h> using namespace std;const int MAX_N 210; const int MAX_M 16;int n…

讲解Mysql InnoDB的MVCC

1. 定义 MVCC是多版本并发控制&#xff08;Multi - Version Concurrency Control&#xff09;的缩写。它是InnoDB存储引擎实现高并发控制的一种机制。在数据库系统中&#xff0c;多个事务可能会同时对数据进行读写操作&#xff0c;而MVCC通过为数据行保存多个版本来解决并发事务…

ZeroMQ Sockets介绍及应用示例

1. 概念解释 ZeroMQ Sockets提供了一种类标准套接字&#xff08;socket-like&#xff09;的 API&#xff0c;是消息导向的通信机制&#xff0c;基于 TCP/UDP 等传输层协议&#xff0c;但封装了底层细节&#xff08;如连接管理、消息路由、缓冲区等&#xff09;&#xff0c;提供…

语音合成之十五 语音合成(TTS)分句生成拼接时的响度一致性问题:现状、成因与对策

语音合成&#xff08;TTS&#xff09;分句生成拼接时的响度一致性问题&#xff1a;现状、成因与对策 引言&#xff1a;分段式文本转语音中的响度一致性挑战业界对响度差异问题的认知拼接语音片段中响度变化的根本原因分段拼接的固有挑战各片段预测韵律特征的差异文本特征和模型…

Android中Binder驱动作用?

Binder驱动的作用与核心功能 Binder驱动是Android系统中实现进程间通信&#xff08;IPC&#xff09;的核心底层组件&#xff0c;它工作于Linux内核层&#xff0c;负责管理跨进程通信的建立、数据传输、资源同步等关键任务。以下是其核心作用及实现细节&#xff1a; 1. ​​进程…

网络学习-TCP协议(七)

一、TCP协议 TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09;是一种面向连接的、可靠的、基于字节流的传输层通信协议。 1、三次握手 客户端&#xff1a; 1、先发起连接&#xff0c;发送SYN置1&#xff0c;seqnum12345(随机值)----半连接…

【Python 基础与实战】从基础语法到项目应用的全流程解析

&#xff08;1&#xff09;列表和元组的区别是什么?如何从列表创建元组?如何从元组创建列表? 列表和元组的区别&#xff1a; 可变性&#xff1a;列表是可变的&#xff0c;即可以对列表进行元素的增、删、改操作。例如&#xff0c;可以使用append()方法添加元素&#xff0c;r…

Docker部署Zookeeper集群

简介 ZooKeeper 是一个开源的分布式协调服务&#xff0c;由 Apache 软件基金会开发和维护。它主要用于管理和协调分布式系统中的多个节点&#xff0c;以解决分布式环境下的常见问题&#xff0c;如配置管理、服务发现、分布式锁等。ZooKeeper 提供了一种可靠的机制&#xff0c;…

【学习笔记】Sophus (Python) 使用文档

以下是一份针对 Sophus 库的 Python 使用文档&#xff0c;涵盖基础概念、安装方法、核心功能及代码示例。内容围绕 SO3&#xff08;3D旋转群&#xff09;和 SE3&#xff08;3D刚体变换群&#xff09;展开&#xff0c;适合机器人学、SLAM、三维几何等领域。 Sophus (Python) 使用…

计算机图形学:(三)MVP变换扩展

Three.js WebGL允许把JavaScript和OpenGL 结合在一起运用&#xff0c;但使用WebGL原生的API来写3D程序非常的复杂&#xff0c;同时需要相对较多的数学知识&#xff0c;对于前端开发者来说学习成本非常高。 Three.js是基于webGL的封装的一个易于使用且轻量级的3D库&#xff0c;T…

MySQL数据库操作合集

一、SQL通用语法 ①SQL语句可以单行或多行书写&#xff0c;以分号结尾。 ②SQL语句可以使用空格/缩进来增强语句可读性。 ③MySQL数据库的SQL语句不区分大小写&#xff0c;关键字建议使用大写。 ④注释&#xff1a; 单行注释&#xff1a; -- 注释内容 或 # 注释内容&#…

传统工程项目管理与业财一体化管理的区别?

在工程项目管理领域&#xff0c;传统管理模式与新兴的业财一体化管理模式正在形成鲜明对比。随着数字化转型的加速&#xff0c;工程行业对高效、透明、协同的管理需求日益迫切。传统工程项目管理依赖人工操作、分散系统和分模块管理&#xff0c;难以应对复杂项目的全生命周期需…

敦煌网测评从环境搭建到风控应对,精细化运营打造安全测评体系

自养号测评&#xff0c;抢占流量为快速提升产品权重和销量&#xff0c;很多卖家常采用自己养号补单测评的方式&#xff0c;技术搭建需要很多要素 一、硬件参数的关联性 在我们使用设备进行注册或操作账号的过程中&#xff0c;系统会记录下大量的系统与网络参数&#xff0c;其中…

redis Pub/Sub 简介 -16 (PUBLISH、SUBSCRIBE、PSUBSCRIBE)

Redis Pub/Sub 简介&#xff1a;PUBLISH、SUBSCRIBE、PSUBSCRIBE Redis Pub/Sub 是一种强大的消息传递范例&#xff0c;可在应用程序的不同部分之间实现实时通信。它是构建可扩展和响应式系统的基石&#xff0c;允许组件在没有直接依赖的情况下进行交互。本章将全面介绍 Redis…

JavaSE核心知识点03高级特性03-01(集合框架)

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 JavaSE核心知识点03高级特性03-01&#xff0…

日志分析-IIS日志分析

环境准备 https://xj.edisec.net/challenges/115 题目要求 windows系统中才有的IIS服务 既然是windows平台&#xff0c;当然需要rdp登录&#xff0c;在ssh登录失败 解题过程 phpstudy--2018站点日志.(.log文件)所在路径&#xff0c;提供绝对路径 Windows服务的日志一般有固定…

一、web安全基础入门

1、Windows命令 文件和目录操作 dir&#xff1a;列出当前目录下的文件和子目录。cd&#xff1a;切换目录&#xff0c;例如 cd C:\Users 切换到C盘的Users目录。md 或 mkdir&#xff1a;创建新目录&#xff0c;如 md testdir。rd 或 rmdir&#xff1a;删除空目录&#xff0c;例…