C++效率掌握之STL库:unordered_map && unordered_set底层剖析

文章目录

看了前面的底层封装后,其实封装的过程及方法都大差不差,unordered_map && unordered_set 也是如此,所以本篇就简单提及一些细节,具体最详细的一些部分可以去看前面的文章

传送门:C++效率掌握之STL库:list底层剖析及迭代器万字详解
传送门:C++效率掌握之STL库:map && set底层剖析及迭代器万字详解

1.unordered_map、unordered_set的基本结构

🚩unordered_set:

cpp 复制代码
template<class K, class V>
class unordered_set
{
	struct SetKeyOfT
	{
		const K& operator()(const K& key)
		{
			return key;
		}
	};
public:
	typedef typename hash_bucket::HashTable<K, K, SetKeyOfT>::const_iterator iterator;
	typedef typename hash_bucket::HashTable<K, K, SetKeyOfT>::const_iterator const_iterator;


	const_iterator begin() const
	{
		return _ht.begin();
	}

	const_iterator end() const
	{
		return _ht.end();
	}

	pair<const_iterator, bool> insert(const K& key)
	{
		pair<typename hash_bucket::HashTable<K, K, SetKeyOfT>::iterator, bool> ret = _ht.Insert(key);
		return pair<const_iterator, bool>(ret.first, ret.second);
	}
private:
	hash_bucket::HashTable<K, K, SetKeyOfT> _ht;
};

🚩unordered_map:

cpp 复制代码
template<class K, class V>
class unordered_map
{
	struct MapKeyOfT
	{
		const K& operator()(const pair<const K, V>& kv)
		{
			return kv.first;
		}
	};
public:
	typedef typename hash_bucket::HashTable<K, pair<const K, V>, MapKeyOfT>::iterator iterator;
	typedef typename hash_bucket::HashTable<K, pair<const K, V>, MapKeyOfT>::const_iterator const_iterator;

	iterator begin()
	{
		return _ht.begin();
	}

	iterator end()
	{
		return _ht.end();
	}

	const_iterator begin() const
	{
		return _ht.begin();
	}

	const_iterator end() const
	{
		return _ht.end();
	}

	pair<iterator, bool> insert(const pair<K, V>& kv)
	{
		return _ht.Insert(kv);
	}

	V& operator[](const K& key)
	{
		pair<iterator, bool> ret = _ht.Insert(make_pair(key, V()));
		return ret.first->second;
	}
private:
	hash_bucket::HashTable<K, pair<const K, V>, MapKeyOfT> _ht;
};

unordered_set 虽然事 k-k 类型,unordered_mapk-v 类型,但是实际上这两个类共用一个哈希表,准确来说是共用同一个模板类型,unordered_set<K,K>unordered_map<K,pair<K,V>>

2.普通迭代器

cpp 复制代码
template<class K, class T, class Ptr, class Ref, class KeyOfT, class HashFunc>
struct HTIterator
{
	typedef HashNode<T> Node;
	typedef HTIterator<K, T, Ptr, Ref, KeyOfT, HashFunc> Self;
	typedef HTIterator<K, T, T*, T&, KeyOfT, HashFunc> Iterator;

	Node* _node;
	const HashTable<K, T, KeyOfT, HashFunc>* _pht;

	/*HTIterator(Node* node, HashTable<K, T, KeyOfT, HashFunc>* pht)
		:_node(node)
		,_pht(pht)
	{}*/

	HTIterator(Node* node, const HashTable<K, T, KeyOfT, HashFunc>* pht)
		:_node(node)
		, _pht(pht)
	{
	}

	// 普通迭代器时,他是拷贝构造
	// const迭代器时,他是构造
	HTIterator(const Iterator& it)
		:_node(it._node)
		, _pht(it._pht)
	{
	}

	Ref operator*()
	{
		return _node->_data;
	}

	Ptr operator->()
	{
		return &_node->_data;
	}

	Self& operator++()
	{
		if (_node->_next)
		{
			// 当前桶还没完
			_node = _node->_next;
		}
		else
		{
			KeyOfT kot;
			HashFunc hf;
			size_t hashi = hf(kot(_node->_data)) % _pht->_table.size();
			// 从下一个位置查找查找下一个不为空的桶
			++hashi;
			while (hashi < _pht->_table.size())
			{
				if (_pht->_table[hashi])
				{
					_node = _pht->_table[hashi];
					return *this;
				}
				else
				{
					++hashi;
				}
			}

			_node = nullptr;
		}

		return *this;
	}

	bool operator!=(const Self& s)
	{
		return _node != s._node;
	}

	bool operator==(const Self& s)
	{
		return _node == s._node;
	}
};

typedef HTIterator<K, T, T*, T&, KeyOfT, HashFunc> Iterator 和构造函数是为 Insert 操作准备的,因为涉及到普通迭代器创建 const 迭代器

🔥值得注意的是: 有人说不是可以通过权限转化吗?但是权限转化是只有涉及引用和指针的类型时才会生效,而这里是模板参数之间的转化

3.const迭代器

unordered_set 本身无论是 const 迭代器还是普通迭代器都会被 typedefconst_iterator

对于 unordered_map 来说,key 是不允许改变的,value 是可以改变的,但是如果像 set 那样写的话 keyvalue 都不能修改了,所以直接在 pairkeyconst ,控制 value 即可

4.insert返回值 operator[]

🚩unordered_set:

cpp 复制代码
pair<const_iterator, bool> insert(const K& key)
{
	//return _ht.Insert(key);
	pair<typename hash_bucket::HashTable<K, K, SetKeyOfT>::iterator, bool> ret = _ht.Insert(key);
	return pair<const_iterator, bool>(ret.first, ret.second);
}

🚩unordered_map:

cpp 复制代码
pair<iterator, bool> insert(const pair<K, V>& kv)
{
	return _ht.Insert(kv);
}

V& operator[](const K& key)
{
	pair<iterator, bool> ret = _ht.Insert(make_pair(key, V()));
	return ret.first->second;
}

这里的转化尤为复杂,一定要看之前文章的详细解析

希望读者们多多三连支持

小编会继续更新

你们的鼓励就是我前进的动力!

相关推荐
进击中的小龙13 小时前
在vscode下的cmake项目里传参调试c++命令行程序
c++·vscode
奔跑吧邓邓子15 小时前
【C++实战(74)】深入C++安全编程:密码学实战之旅
c++·安全·实战·密码学·安全编程
明天会有多晴朗16 小时前
C语言入门教程(第1讲):最通俗的C语言常见概念详解与实战讲解
c语言·开发语言·c++
Larry_Yanan16 小时前
QML学习笔记(二十四)QML的Keys附加属性
c++·笔记·qt·学习·ui
龙木之森17 小时前
纯 C++ 开发的 Telegram Bot 框架
c++·tui·telegram·bot
hqwest18 小时前
QT肝8天09--用户列表
开发语言·c++·qt·上位机·qt开发
眠りたいです18 小时前
基于脚手架微服务的视频点播系统-脚手架开发部分-brpc中间件介绍与使用及二次封装
c++·微服务·中间件·rpc·架构·brpc
明天会有多晴朗19 小时前
深度剖析 C++ 之内存管理篇
c语言·开发语言·c++
Starry_hello world21 小时前
C++ 二分算法(1)
c++·算法·有问必答
眠りたいです21 小时前
基于脚手架微服务的视频点播系统-脚手架开发部分-jsoncpp,protobuf,Cpp-httplib与WebSocketpp中间件介绍与使用
c++·websocket·微服务·中间件·json·protobuf·cpp-httplib