SGISTL源码探究-关联式容器:hash_map

TB6600驱动器共阴共阳接法傻傻分不清?一张图搞定STM32与42步进电机的接线避坑指南 本文详细解析了TB6600驱动器共阴共阳接法的本质区别,提供了STM32与42步进电机的高效连接方案。通过实际案例和接线图示,帮助读者避免常见错误,确保驱动器与MCU的安全连接,提升项目稳定性。 阅读详情

前言

在上一小节,我们分析了hash_set的实现,本小节我们将针对hash_map进行分析。它大部分也是调用的hashtable,不过它与map的区别也是因为底层的实现不同,所以map具有自动排序功能,而hash_map没有。
接下来我们来看看hash_map是如何实现的。

hash_map的实现

还是分为定义部分及其数据结构、构造函数、常用操作这三部分。关于hash_map的迭代器,是使用的hashtable的迭代器,并且是const型的,这就说明hash_map与map一样,不允许我们修改key值。

定义及其数据结构
#ifndef __STL_LIMITED_DEFAULT_TEMPLATES
template <class Key, class T, class HashFcn = hash<Key>,
          class EqualKey = equal_to<Key>,
          class Alloc = alloc>
#else
template <class Key, class T, class HashFcn, class EqualKey,
          class Alloc = alloc>
#endif
class hash_map
{
private:
  //这里定义hashtable成员,pair里面的key是常量类型的
  typedef hashtable<pair<const Key, T>, Key, HashFcn,
                    select1st<pair<const Key, T> >, EqualKey, Alloc> ht;
  ht rep;

public:
  //别名部分
  typedef typename ht::key_type key_type;
  typedef T data_type;
  typedef T mapped_type;
  typedef typename ht::value_type value_type;
  typedef typename ht::hasher hasher;
  typedef typename ht::key_equal key_equal;

  typedef typename ht::size_type size_type;
  typedef typename ht::difference_type difference_type;
  typedef typename ht::pointer pointer;
  typedef typename ht::const_pointer const_pointer;
  typedef typename ht::reference reference;
  typedef typename ht::const_reference const_reference;

  typedef typename ht::iterator iterator;
  typedef typename ht::const_iterator const_iterator;

  //取得哈希函数以及比较key的函数
  hasher hash_funct() const { return rep.hash_funct(); }
  key_equal key_eq() const { return rep.key_eq(); }
构造函数
public:
  //默认大小为100,不过会被hashtable进行调整
  hash_map() : rep(100, hasher(), key_equal()) {}
  //禁止隐式转换,只指定大小,其他默认
  explicit hash_map(size_type n) : rep(n, hasher(), key_equal()) {}
  //指定大小以及哈希函数
  hash_map(size_type n, const hasher& hf) : rep(n, hf, key_equal()) {}
  //三者都指定
  hash_map(size_type n, const hasher& hf, const key_equal& eql)
    : rep(n, hf, eql) {}

  /* 根据范围进行构造 */
#ifdef __STL_MEMBER_TEMPLATES
  template <class InputIterator>
  hash_map(InputIterator f, InputIterator l)
    : rep(100, hasher(), key_equal()) { rep.insert_unique(f, l); }
  template <class InputIterator>
  hash_map(InputIterator f, InputIterator l, size_type n)
    : rep(n, hasher(), key_equal()) { rep.insert_unique(f, l); }
  template <class InputIterator>
  hash_map(InputIterator f, InputIterator l, size_type n,
           const hasher& hf)
    : rep(n, hf, key_equal()) { rep.insert_unique(f, l); }
  template <class InputIterator>
  hash_map(InputIterator f, InputIterator l, size_type n,
           const hasher& hf, const key_equal& eql)
    : rep(n, hf, eql) { rep.insert_unique(f, l); }

#else
  hash_map(const value_type* f, const value_type* l)
    : rep(100, hasher(), key_equal()) { rep.insert_unique(f, l); }
  hash_map(const value_type* f, const value_type* l, size_type n)
    : rep(n, hasher(), key_equal()) { rep.insert_unique(f, l); }
  hash_map(const value_type* f, const value_type* l, size_type n,
           const hasher& hf)
    : rep(n, hf, key_equal()) { rep.insert_unique(f, l); }
  hash_map(const value_type* f, const value_type* l, size_type n,
           const hasher& hf, const key_equal& eql)
    : rep(n, hf, eql) { rep.insert_unique(f, l); }

  hash_map(const_iterator f, const_iterator l)
    : rep(100, hasher(), key_equal()) { rep.insert_unique(f, l); }
  hash_map(const_iterator f, const_iterator l, size_type n)
    : rep(n, hasher(), key_equal()) { rep.insert_unique(f, l); }
  hash_map(const_iterator f, const_iterator l, size_type n,
           const hasher& hf)
    : rep(n, hf, key_equal()) { rep.insert_unique(f, l); }
  hash_map(const_iterator f, const_iterator l, size_type n,
           const hasher& hf, const key_equal& eql)
    : rep(n, hf, eql) { rep.insert_unique(f, l); }
#endif /*__STL_MEMBER_TEMPLATES */
常用操作
public:
  //hash_map里面的元素个数
  size_type size() const { return rep.size(); }
  size_type max_size() const { return rep.max_size(); }
  //判空
  bool empty() const { return rep.empty(); }
  //交换
  void swap(hash_map& hs) { rep.swap(hs.rep); }
  friend bool
  operator== __STL_NULL_TMPL_ARGS (const hash_map&, const hash_map&);

  //返回起始/末尾迭代器
  iterator begin() { return rep.begin(); }
  iterator end() { return rep.end(); }
  const_iterator begin() const { return rep.begin(); }
  const_iterator end() const { return rep.end(); }

public:
  //插入元素
  pair<iterator, bool> insert(const value_type& obj)
    { return rep.insert_unique(obj); }
  //范围插入
#ifdef __STL_MEMBER_TEMPLATES
  template <class InputIterator>
  void insert(InputIterator f, InputIterator l) { rep.insert_unique(f,l); }
#else
  void insert(const value_type* f, const value_type* l) {
    rep.insert_unique(f,l);
  }
  void insert(const_iterator f, const_iterator l) { rep.insert_unique(f, l); }
#endif /*__STL_MEMBER_TEMPLATES */
  pair<iterator, bool> insert_noresize(const value_type& obj)
    { return rep.insert_unique_noresize(obj); }    
  //查找键值为key的元素
  iterator find(const key_type& key) { return rep.find(key); }
  const_iterator find(const key_type& key) const { return rep.find(key); }

  //重载[]操作符
  T& operator[](const key_type& key) {
    //这里调用了之前分析hashtable中的那个查找若没有则插入的函数
    return rep.find_or_insert(value_type(key, T())).second;
  }
  //计算键值为key的元素
  size_type count(const key_type& key) const { return rep.count(key); }

  pair<iterator, iterator> equal_range(const key_type& key)
    { return rep.equal_range(key); }
  pair<const_iterator, const_iterator> equal_range(const key_type& key) const
    { return rep.equal_range(key); }

  //删除操作
  size_type erase(const key_type& key) {return rep.erase(key); }
  void erase(iterator it) { rep.erase(it); }
  void erase(iterator f, iterator l) { rep.erase(f, l); }
  void clear() { rep.clear(); }

public:
  //判断是否需要重建表
  void resize(size_type hint) { rep.resize(hint); }
  //计算bucket个数
  size_type bucket_count() const { return rep.bucket_count(); }
  size_type max_bucket_count() const { return rep.max_bucket_count(); }
  //计算bucket中的节点数
  size_type elems_in_bucket(size_type n) const
    { return rep.elems_in_bucket(n); }
};

//重载==操作符
template <class Key, class T, class HashFcn, class EqualKey, class Alloc>
inline bool operator==(const hash_map<Key, T, HashFcn, EqualKey, Alloc>& hm1,
                       const hash_map<Key, T, HashFcn, EqualKey, Alloc>& hm2)
{
  return hm1.rep == hm2.rep;
}

#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER

template <class Key, class T, class HashFcn, class EqualKey, class Alloc>
inline void swap(hash_map<Key, T, HashFcn, EqualKey, Alloc>& hm1,
                 hash_map<Key, T, HashFcn, EqualKey, Alloc>& hm2)
{
  hm1.swap(hm2);
}

#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */

小结

本小节介绍了hash_map的实现,它同样也支持下标运算,这个操作全靠hashtable中提供的find_or_insert操作实现。并且hash_map也不允许键值被改变。
在下节中,我们将分别介绍hash_set和hash_map的兄弟hash_multiset和hash_multimap。

WPF实战:利用Live Charts实现高性能动态曲线可视化 本文详细介绍了如何在WPF中使用Live Charts实现高性能动态曲线可视化,特别适用于工业监控和金融分析等实时数据场景。通过增量渲染、内存复用和硬件加速等核心技术,Live Charts能够高效处理高频数据更新,显著提升图表流畅度。文章提供了从基础实现到工业级优化的完整解决方案,帮助开发者应对各种性能挑战。 阅读详情

相关推荐

亚博k210视觉模块与stm32双向通信

【代码】亚博k210视觉模块与stm32双向通信。

w_150831的博客 3246

SGISTL源码阅读二十 map关联式容器

SGISTL源码阅读二十 map关联式容器 前言 map是一种关联式容器,底层同样是红黑树实现的,所有的元素都会根据元素的键值自动被排序。map中所有的元素pair,pair将两个数据合成一个,将pair的第一个值视为键值,第二个值视为实值,非常符合key``````value的要求。 我们知道set保证了数据的唯一性,map也一样,在map中不允许两个元素拥有相同的键值。 深入源码 map的定义...

Lyn&Xx 470

首个FDA认证开源医学影像AI平台Comp2Comp:从CT自动分析到临床部署全解析

深度学习模型在医学影像分析领域正成为变革性力量,其核心原理是通过卷积神经网络自动学习图像特征,实现精准分割与检测。这一技术价值在于将高度依赖医生经验的定性、主观判断,转化为高效、客观、可重复的定量分析,极大提升了诊断的一致性和工作效率。在应用场景上,医学影像AI已广泛渗透于疾病筛查、辅助诊断、预后评估及治疗方案规划等多个环节。本文聚焦于获得FDA 510(k)认证的开源平台Comp2Comp,它集成了主动脉钙化评分和椎体骨密度分析双任务,通过串联式的U-Net分割网络与目标检测模型,构建了从DICOM预处理

weixin_33725126的博客 653

SGISTL源码阅读 map与hash_map之间的区别

SGISTL源码阅读 map与hash_map之间的区别 前言 之前我们已经学习过了这两种关联式容器,他们可以用来存放键值对,并且不可存放重复键值(因为内部调用了insert_unique),他们所提供的很多插入删除方法也是非常类似的。现在我们来分析一下他们之间的区别。 我们知道map的底层容器是红黑树,hash_map的底层是hashtable,所以他们之间的区别主要是由他们底层的容器来带的,...

Lyn&Xx 385

PSpice 导入 LTspice 仿真实验 --(如何解决PSpice模型无法使用的错误)

参考了网上第三方器件导入LTspice的博客和资料,不论是哪个公司下载的SPICE模型导入LTspice的方法都类似。如果遇到导入报错的情况可以先看一下报错提示,如果通过语法修改实现功能的则说明可以进行仿真,当然性能可能与官方给的模型存在一点出入,但做一个基本的功能验证本人认为还是可以的,总比做出板子用不了或者完全不匹配的要好一些。

伊丽莎白的学习之路 8998

TSMaster实战:手把手教你用C小程序发送自定义CAN报文(附完整代码)

本文详细解析了如何使用TSMaster的C小程序功能实现自定义CAN报文发送,涵盖环境配置、DBC集成、按键触发等实战技巧。通过完整代码示例和高级调试方法,帮助汽车电子工程师快速掌握TSMaster在CAN总线通信中的灵活应用,提升开发效率。

weixin_29184371的博客 574

详细解说STL hash_map系列

<br />0 为什么需要hash_map  <br />      用过map吧?map提供一个很常用的功能,那就是提供key-value的存储和查找功能。例如,我要记录一个人名和相应的存储,而且随时增加,要快速查找和修改:  <br /><br />岳不群-华山派掌门人,人称君子剑 <br />张三丰-武当掌门人,太极拳创始人 <br />东方不败-第一高手,葵花宝典 <br />      ...这些信息如果保存下来并不复杂,但是找起来比较麻烦。例如我要找"张三丰"的信息,最傻的方法就是取得所有的记录

lubosheng的专栏 315

Windows显卡TDR超时导致Unity崩溃?手把手教你修改注册表延长响应时间

本文详细解析了Windows显卡TDR超时导致Unity崩溃的问题,并提供了修改注册表延长响应时间的完整解决方案。通过调整TdrDelay和TdrDdiDelay键值,开发者可以有效避免D3D11设备丢失错误,提升Unity编辑器的稳定性。文章还包含显卡驱动优化、系统性能调优等实用技巧,帮助开发者彻底解决编辑器崩溃问题。

weixin_33737774的博客 622

hash_map介绍与使用

http://stackoverflow.com/questions/5908581/is-hash-map-part-of-the-stl http://blog.youkuaiyun.com/dongtingzhizi/article/details/8629285

holybin的专栏 1万+

AutoCAD中圆弧折线化方法与实现

在AutoCAD中,圆弧折线化是将圆弧曲线转换为由一系列线段组成的折线曲线的过程。本文将介绍如何使用LISP编写代码来实现圆弧折线化,并提供相应的源代码。上述示例代码将生成一个以坐标原点为圆心、起点为(5.0, 0.0, 0.0)、终点为(0.0, 5.0, 0.0)、半径为5.0、角度为90度的圆弧的折线表示。通过使用上述的LISP代码,你可以在AutoCAD中实现将圆弧转换为折线的功能。你可以根据需要修改代码中的参数来适应不同的圆弧转换需求。函数,并传入圆弧的起点、终点、圆心、半径和角度参数。

VcuOcaml的博客 1417

射频仿真软件:ADS (Advanced Design System)_(29).ADS脚本编程与自动化

ADS脚本编程为射频设计提供了强大的自动化工具,可以帮助用户实现设计流程的优化、参数扫描和优化、结果分析和报告生成等任务。选择合适的脚本语言(Python、Tcl、AEL)并合理设置ADS环境,可以显著提高设计效率和准确性。通过实际项目中的应用案例,我们可以更好地理解如何利用脚本编程解决复杂的射频设计问题。希望本文对您的ADS脚本编程学习有所帮助。

kkchenjj的博客 2470

SGISTL源码探究-关联式容器:hash_multimap

前言本小节将介绍hash_multimap的源码实现,它与hash_map的不同与map和multimap的不同类似,所以我们可以一边分析它们的不同之处,一边顺便复习hash_map。hash_multimap的实现定义及数据结构#ifndef __STL_LIMITED_DEFAULT_TEMPLATES template <class Key, class T, class HashFcn =

Move_now的博客 1117

SAP会计凭证导入ABAP开发模板+注意点—附带源码

开发并不仅仅只要考虑实现的功能,只实现功能的是程序,考虑到使用场景的是工程。使用bapi校验创建会计凭证的数据,报错和参数和正式创建一致。用途,防止产生错误的凭证,即使财务凭证可以冲销。正式创建会计凭证。隐藏的坑。

小九啥也不会 1232

SGISTL源码阅读二十五 hash_map 关联式容器

SGISTL源码阅读二十五 hash_map 关联式容器 前言 前面我们已经分析了底层容器为红黑树的map和hashtable,而接下来我们要分析的hash_map,其底层容器为hashtable。 深入源码 hash_map的定义部分 #ifndef __STL_LIMITED_DEFAULT_TEMPLATES template &amp;lt;class Key, class T, class H...

Lyn&Xx 232

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

SGISTL源码探究-关联式容器:hash_multiset

前言在上几节中我们分析了hashtable以及hash_set还有hash_map的实现,hash_set以及hash_map都不允许有重复的key存在,而hashtable提供了允许插入重复元素的操作insert_equal,对应实现的则是hash_multiset以及hash_multimap。 接下来我们先看看hash_multiset的实现,它和hash_set的实现很类似。hash_mu

Move_now的博客 1090

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

SGISTL源码探究-关联式容器:hash_set

前言在上小节中,我们已经分析了hashtable的实现,它只是hash_set和hash_map的预备知识。在本小节中,我们将进入到关联式容器hash_set的源码中,一窥究竟。hash_set的实现由于hash_set并没有自己定义的迭代器,所以接下来我们先对它的定义部分以及数据结构进行分析,然后是它的构造函数以及常用操作等。定义部分及数据结构#ifndef __STL_LIMITED_DEFAU

Move_now的博客 876

SGISTL源码-容器 笔记

本文是在阅读SGI STL v3.3源码中,遇到的一些问题及有意思的点。本文建立在已经观看过侯捷老师STL源码剖析课程的基础上。是在阅读源码过程中,对其中的内容进行补充、修饰。

weixin_46065476的博客 596

STL源码剖析 - 第5章 关联式容器 - RB-tree(红黑树)

5.1 树的导览      标准的STL关联式容器分为set(集合)和map(映射表)两大类,以及这两大类的衍生体multiset(多键集合)和multimap(多键映射表)。这些容器的底层机制均以RB-tree(红黑树)完成。RB-tree也是一个独立的容器,但并不开放给外界使用。 此外,SGI STL还提供了一个不在标准规格之列的关联式容器:hash table(散列表),以及以此hash

灯火阑珊处 758

《STL源码剖析》——第五、六章:关联容器与算法

第五章、关联容器 5.0、关联容器 标准的STL关联式容器分为set(集合)和map(映射表)两大类,以及这两大类的衍生体multiset(多键集合)和multimap(多键映射表)。这些容器的底层机制均以RB-tree(红黑树)完成。RB-tree也是一个独立容器,但并不开放给外界使用。 SGISTL还提供了一个不在标准规格之列的关联式容器:hash_table(散列表),以及以此has...

weixin_42637495的博客 350

学习笔记----STL源码剖析

自己的学习笔记

2301_80428401的博客 684

STL学习笔记(一)---概述

STL提供了六大组件,彼此之间可以用组合套用,分别是容器、算法、迭代器、适配器与空间配置器。 容器:各种数据结构,如vector、 list、 deque、 set、 map等,用来存放数据,从实现角度来看, STL容器是一种class template。 算法:各种常用的算法,如sort、 find、 copy、 for_ each,从实现的角度来看,STL算法是一种 function template。 迭代器:扮演了容器与算法之间的胶合剂,是所谓的“泛型指针”,共有五种类型,从实现角度来看,迭代器是一

qq_44272681的博客 263

❤️ 【STL 序列式容器】 vector 超硬核源码剖析 ❤️

目录前言第4章 序列式容器4.1 容器的概念与分类4.1.1 序列式容器4.2 vector4.2.1 vector概述4.2.2 vector定义摘要4.2.3 vector的迭代器4.2.4 vector的数据结构4.2.5 vector的构造与内存管理4.2.6 vector的元素操作 前言 国庆七天假宛如一天假,定睛一看又要上班… 国庆档电影院热闹了不少,《长津湖》真的值回票价,吴京真不错,意外的是易烊千玺竟然演出了小戏骨的感觉,整部电影很有感染力,点赞! 外滩一如既往的人山人海,不过每次抱着去看人

GOOD GOOD STUDY, DAY DAY UP 887

STL源码分析之RB-tree结构简析

所谓关联容器:          每笔数据(每个元素)都有一个键值(key)和一个实值(value)。当元素被插入到关联式容器中时,容器内部结构(可能是RB-Tree 也可能是hash-table)便依照其键值大小,以某种特定规则将这个元素置放于适当的位置。          关联容器没有所谓的头尾(只有最大元素和最小元素),所以不会有所谓的push_back(), push_front(),

博客 795

C++ STL中哈希表 hash_map从头到尾详细介绍

0 为什么需要hash_map 用过map吧?map提供一个很常用的功能,那就是提供key-value的存储和查找功能。例如,我要记录一个人名和相应的存储,而且随时增加,要快速查找和修改: 岳不群-华山派掌门人,人称君子剑 张三丰-武当掌门人,太极拳创始人 东方不败-第一高手,葵花宝典 ... 这些信息如果保存下来并不复杂,但是找起来比较麻烦。例如我要找"张三丰"的信

susandebug 7万+

STL中map使用陷阱

最近在项目开发中使用到了SGI版本的STL中的map,结果遇到了非预期的现象。        众所周知,map 的底层是用红黑树来管理key-value关系的,因此在find时,效率极高,但同样这也带来了某些非预期的空间开销。

异客 2492
上一篇: SGISTL源码探究-关联式容器:hash_set
下一篇: SGISTL源码探究-关联式容器:hash_multiset
UKey_
博客等级 码龄10年 258粉丝 186原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值