zoukankan      html  css  js  c++  java
  • 如何在STL的map中使用结构体作为键值

      这里首先给出容器map的原型:

    template <
    	class Key,
    	class T, 
    	class Compare = less<Key>,
    	class Alloc = alloc>
    class map{
    	...
    }
    

      可以看到模板参数一共有四个,第一个就是Key,即键;第二个就是值;第四个就是空间配置器,默认使用alloc(随STL版本不同而不同)。那么第三个是啥?

      我们知道,map的底层数据结构,其实是树,更确切的说,是一个RB-tree(红黑树)。RB-tree树在进行插入时,会按照一定的规则把新元素插入特定位置。相应的,进行删除操作时,也会按一定规则修改树的结构。此外,树形结构也是高效率查询的基本保证。但是,插入、删除、查询时都要依赖与节点之间的比较,对于map来说,我们必须提供对Key进行比较的函数或操作符。这也就是第三个模板参数的意义。

      默认情况下,第三个模板参数使用less<Key>类型,其中less<T>是一个仿函数。下面给出less的定义:

    template<class _Ty>
    	struct less
    		: public binary_function<_Ty, _Ty, bool>
    	{	// functor for operator<
    	bool operator()(const _Ty& _Left, const _Ty& _Right) const
    		{	// apply operator< to operands
    		return (_Left < _Right);
    		}
    	};
    

      如果创建一个less类的对象less_obj,然后使用less_obj(A,B)这样的写法,就相当于调用了less的operator()方法。而最终执行时,会自动获取A与B的类型,并使用此类型的operator<来实现less类的operator()方法。到现在为止,就理清了map中的第三个模板参数的所有问题。

      接下来的问题就是,如何在map中使用一个结构体作为Key。举例来说,现在有一个结构体:

    typedef struct _info_head{
    	u_int src_ip;
    	u_int dest_ip;
    	u_int src_port; 
    	u_int dest_port;
    }info_head;
    

      如果直接使用info_head这个结构体来填入map中的第一个模板参数的位置,并且不指定第三个模板参数的话,那么就会使用less<info_head>作为map中对键值进行比较的操作符。而通过上述分析,在less<info_head>中最终使用的,是info_head类型的operator<操作符。那么显然的,只给出上边的简单的对结构体的定义,是不够的。因此,要想使用结构体来作为map中的Key,那就必须为此结构体重载并实现operator<操作符。如果没能做到这一点,就会在编译时报错,因为编译器找不到对应的operator<。其中,VS2010下的编译错误代码是:error C2784。

      修改后的结构体代码如下:

    typedef struct _info_head{
    	u_int src_ip;
    	u_int dest_ip;
    	u_int src_port; 
    	u_int dest_port;
    
    	bool operator<(const struct _info_head & other) const {
    	//Must be overloaded as public if this struct is being used as the KEY in map.
    		if (this->src_ip < other.src_ip) return true;
    		if (this->dest_ip < other.dest_ip) return true;
    		if (this->src_port < other.src_port) return true;
    		if (this->dest_port < other.dest_port) return true;
    		return false;
    	}
    }info_head;
    

      不过这并不是唯一的办法。另外一种方式,就是自己写一个仿函数,实现对info_head类型的比较。然后在info_head作为map中第一个模板参数的时候,填入这个仿函数作为map的第三个模板参数。不过这样做显然不如上边这种办法简单,这里也不具体叙述了。

  • 相关阅读:
    2018年3月20日java
    2018年3月19日Java
    浏览器执行js代码的机制--对于我们深入了解js有很大的帮助,同时面试时候也都能用得到。
    如果用css的border属性画一个三角形
    js事件(event)的运行原理
    如何通过源生js获取一个元素的具体样式值 /* getCss:获取指定元素的具体样式的属性值 curElement:[dom对象] attr:[string] */
    js创建对象的高级模式
    查看release的SHA1
    集成百度地图定位和导航功能时出现包冲突
    【十次方基础教程(后台)】MongoDB相关
  • 原文地址:https://www.cnblogs.com/superpig0501/p/4098310.html
Copyright © 2011-2022 走看看