(Boolan) C++ STL与泛型编程

本文探讨了C++ STL中的万用Hash Function,如何为自定义类型指定hash function,并展示了C++ TR1之后STL提供的通用解决方案。此外,还介绍了tuple的用法和实现原理,以及TypeTraits在不同C++版本中的变化。文章还讨论了moveable元素对容器(如vector和list)性能的影响。
摘要由CSDN通过智能技术生成

关于STL的话题已经探讨了好几个篇了,今天来讨论一下剩下的一些内容吧

一个万用的hash function

使用以Hash Table为底层的容器,比如unordered_map(hash_map),在使用个过程中,需要有计算hash code的方法来计算出元素在hashtable中的具体位置。
那么对于自定义类型来说,需要指定对应的Hash Function,只有这样才能在使用的过程,系统找到对应元素应该插入的位置,以便系统自动管理我们需要插入到容器中的各个元素。关于这个函数该如何定义,对于不同个自定义类型来说并不相同,也没有办法找到一个通用的方式,毕竟石头类和动物类,他们各自的hash function多少会有些区别吧,具体的定义,还需要依靠开发这自己了。
那么,为什么后还会有关于个万用的hash function呢?关于这个问题,先放下不说,咱们先来看看关于指定hash function的方式吧。

  • 指定自定义的hash function的方法一
#include<functional>
class Customer{
      //........
};
//这是一个自定义的类,如果使用他作为hashtable为底层的容器时
//系统需要知道如何把他插入到hashtable中的具体位置去


//通过一个类,重载了操作符()的方式,形成了一个仿函数(函数对象)
class CustomerHash
{
public:
      std::size_t operator()(const Customer& c) const{
            return /*........*/;
      }
};

//使用
unordered_set<Customer, CustomerHash> customers;
//声明容器变量时,指定的第二参数,就是对应的Hash Function
//实际在第二参数中指定的是一个函数对象
  • 指定自定义的hash function的方法二
size_t customer_hash_func(const Customer& c)
{
        return /*......*/;
}

//使用
unorder_set<Customer, size(*) (const Cunstomer&)> customers(20, customer_hash_func);
//这个方法实际是通过指定了一个函数指针的方式来通知容器,对于这个自定义类到底应该使用哪个hash function
  • 指定自定义的hash function的方法三
//以struct hash 偏特化形式实现hash function
class MyString
{
private:
      char* _data;
      size_t _len;
};

namespace std;
{
      template<>
      struct hash<MyStrinng>
      {
              size_t operatoe()(const MyString& s) const noexcept{
                      return hash<string>()(string(s.get()));
              }
      }
}

那么通过这三种方式可以指定需要的hash function,但是到底能不能有一个万能的hash function呢?不论自定义的的class,内涵的成员是由什么组成,总归都是有基本数据类型所组成(比如int、char、double等),而之前我们也提过,基本数据类型,STL是提供了一套Hash Function的实现代码的。那么,能否依靠之前我们提到的方法将hash code相加来获取该对象的hash code呢?(例如下方代码)

class CustomerHash
{
public:
      std::size_t operator()(const Customer& c) const{
            return std::hash<std::string>()(c.fname) 
                  + std::hash<std::string>()(c.Iname) 
                  + std::hash<long><c.no);
      }
}
//这个方法可以实现出计算Hash code的功能,但是,不得不提出的就是
//这个方法其实对于hash code的重复概率比较高,因为只是简单的相累加嘛。而重复的hash code 会导致“bucket”中的元素过多,影响查询的效率

其实在 C++ TR1 的版本后,STL为我么提供了一套万用的Hash Function。那么应该如何使用呢?咱们就先来看看吧。

//使用万能的Hash Function
class CustomerHash
{
public:
      std::size_t operator()(const Cunstomer& c) const {
            return hash_val(c.fname, c,Iname, c.no);  
            //在此,只需要调用hash_val函数,并把每个成员的值传递给他就行了
      }
}

咱们看过了这个万用Hash Functon的使用,那么他其中的实现原理到底是什么呢?咱们来看看他的代码吧。

#include<functional>
template<typename T>
inline void hash_combine(size_t& seed, const T& val){
        seed = std::hash<T>(val) + 0x9e3779b9
              + (seed << 6) + (seed >> 2);
}

template<typename T>
inline void hash_val(size_t& seed, const T& val){
      hash_combine(seed, val);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值