对于set这个STL容器来说,就实现来说,我了解到的版本,是通过RB-Tree的方式实现的,内部逻辑似乎是采用Tree结构的平行方式进行展开,换句话说也就是将Tree保存在类似vector这样的线性结构中,不过,这篇帖子并不在于讨论内部结构,而是具体使用中出现的自定义比较的几种方式。

set的话,默认情况,可以不指定第二个模板参数,但是,如果使用非基础类型的话,是需要指定第二个模板参数,用来进行比较的。

我这里以几种方式来实现,原理基本上是相同的,运行结果是完全相同的,不过实现的方式却各有特点:

重载<操作符
view plaincopy to clipboardprint?
#include <iostream>  
#include <set>  
using namespace std;  
#define INT_PTR( ptr ) ( reinterpret_cast<int>( ptr ) )  
class MyClass  
{  
public:  
    MyClass( int data ) : m_iData( data )  
    {   
        cout << INT_PTR(this) << "|default constructor(" << m_iData << ")" << endl;   
    }  
    MyClass( const MyClass& o )   
    {   
        cout << INT_PTR(this) << "|copy constructor from:" << INT_PTR(this) << "|(" << o.data() << ")" <<  endl;   
        m_iData = o.data();  
    }  
    ~MyClass()   
    {   
        cout << INT_PTR(this) << "|destructor (" << m_iData << ")" << endl;   
    }  
    inline int data() const { return m_iData ; }  
private:  
    int m_iData;  
};  
inline bool operator < ( const MyClass & l , const MyClass & r  )  
{  
    return l.data() < r.data();  
};  
int main()  
{  
    set<MyClass> s;  
    s.insert( MyClass(1) );  
    s.insert( MyClass(3) );  
    s.insert( MyClass(2) );  
    s.insert( MyClass(1) );  
    return 1;  
}  
#include <iostream>
#include <set>
using namespace std;
#define INT_PTR( ptr ) ( reinterpret_cast<int>( ptr ) )
class MyClass
{
public:
    MyClass( int data ) : m_iData( data )
    {
        cout << INT_PTR(this) << "|default constructor(" << m_iData << ")" << endl;
    }
    MyClass( const MyClass& o )
    {
        cout << INT_PTR(this) << "|copy constructor from:" << INT_PTR(this) << "|(" << o.data() << ")" <<  endl;
        m_iData = o.data();
    }
    ~MyClass()
    {
        cout << INT_PTR(this) << "|destructor (" << m_iData << ")" << endl;
    }
    inline int data() const { return m_iData ; }
private:
    int m_iData;
};
inline bool operator < ( const MyClass & l , const MyClass & r  )
{
    return l.data() < r.data();
};
int main()
{
    set<MyClass> s;
    s.insert( MyClass(1) );
    s.insert( MyClass(3) );
    s.insert( MyClass(2) );
    s.insert( MyClass(1) );
    return 1;
}

这种方式相对比较简单一些,针对MyClass实现全局的<操作符。因为STL的内部,基本上全部是以<操作符为基础进行比较的,对于其他的比较,按照一定得规则,全部转化为<操作符

特化less模板类
view plaincopy to clipboardprint?
#include <iostream>  
#include <set>  
using namespace std;  
#define INT_PTR( ptr ) ( reinterpret_cast<int>( ptr ) )  
class MyClass  
{  
public:  
    MyClass( int data ) : m_iData( data )  
    {   
        cout << INT_PTR(this) << "|default constructor(" << m_iData << ")" << endl;   
    }  
    MyClass( const MyClass& o )   
    {   
        cout << INT_PTR(this) << "|copy constructor from:" << INT_PTR(this) << "|(" << o.data() << ")" <<  endl;   
        m_iData = o.data();  
    }  
    ~MyClass()   
    {   
        cout << INT_PTR(this) << "|destructor (" << m_iData << ")" << endl;   
    }  
    inline int data() const { return m_iData ; }  
private:  
    int m_iData;  
};  
namespace std  
{  
    template<> struct less<MyClass>  
    {  
        bool operator()( const MyClass & l , const MyClass & r ) const 
        {  
            return l.data() < r.data() ;  
        }  
    };  
};  
int main()  
{  
    set<MyClass> s;  
    s.insert( MyClass(1) );  
    s.insert( MyClass(3) );  
    s.insert( MyClass(2) );  
    s.insert( MyClass(1) );  
    return 1;  

#include <iostream>
#include <set>
using namespace std;
#define INT_PTR( ptr ) ( reinterpret_cast<int>( ptr ) )
class MyClass
{
public:
    MyClass( int data ) : m_iData( data )
    {
        cout << INT_PTR(this) << "|default constructor(" << m_iData << ")" << endl;
    }
    MyClass( const MyClass& o )
    {
        cout << INT_PTR(this) << "|copy constructor from:" << INT_PTR(this) << "|(" << o.data() << ")" <<  endl;
        m_iData = o.data();
    }
    ~MyClass()
    {
        cout << INT_PTR(this) << "|destructor (" << m_iData << ")" << endl;
    }
    inline int data() const { return m_iData ; }
private:
    int m_iData;
};
namespace std
{
    template<> struct less<MyClass>
    {
        bool operator()( const MyClass & l , const MyClass & r ) const
        {
            return l.data() < r.data() ;
        }
    };
};
int main()
{
    set<MyClass> s;
    s.insert( MyClass(1) );
    s.insert( MyClass(3) );
    s.insert( MyClass(2) );
    s.insert( MyClass(1) );
    return 1;
}

这种方式较之前者,能够提供更多的编译期信息,不过,其实原理是一样的。

注意一点:必须放入std的命名空间中,否则会报错“不在相同的命名空间”。

因为我们特化的是一个命名空间的类,而不是自己重写。

实现自己的比较对象类
view plaincopy to clipboardprint?
#include <iostream>  
#include <set>  
using namespace std;  
#define INT_PTR( ptr ) ( reinterpret_cast<int>( ptr ) )  
class MyClass  
{  
public:  
    MyClass( int data ) : m_iData( data )  
    {   
        cout << INT_PTR(this) << "|default constructor(" << m_iData << ")" << endl;   
    }  
    MyClass( const MyClass& o )   
    {   
        cout << INT_PTR(this) << "|copy constructor from:" << INT_PTR(this) << "|(" << o.data() << ")" <<  endl;   
        m_iData = o.data();  
    }  
    ~MyClass()   
    {   
        cout << INT_PTR(this) << "|destructor (" << m_iData << ")" << endl;   
    }  
    inline int data() const { return m_iData ; }  
private:  
    int m_iData;  
};  
struct MyClassLess: public binary_function< MyClass , MyClass , bool >  
{  
    bool operator()( const MyClass & l , const MyClass & r ) const 
    {  
        return l.data() < r.data() ;  
    }  
};  
int main()  
{  
    set<MyClass , MyClassLess > s;  
    s.insert( MyClass(1) );  
    s.insert( MyClass(3) );  
    s.insert( MyClass(2) );  
    s.insert( MyClass(1) );  
    return 1;  

#include <iostream>
#include <set>
using namespace std;
#define INT_PTR( ptr ) ( reinterpret_cast<int>( ptr ) )
class MyClass
{
public:
    MyClass( int data ) : m_iData( data )
    {
        cout << INT_PTR(this) << "|default constructor(" << m_iData << ")" << endl;
    }
    MyClass( const MyClass& o )
    {
        cout << INT_PTR(this) << "|copy constructor from:" << INT_PTR(this) << "|(" << o.data() << ")" <<  endl;
        m_iData = o.data();
    }
    ~MyClass()
    {
        cout << INT_PTR(this) << "|destructor (" << m_iData << ")" << endl;
    }
    inline int data() const { return m_iData ; }
private:
    int m_iData;
};
struct MyClassLess: public binary_function< MyClass , MyClass , bool >
{
    bool operator()( const MyClass & l , const MyClass & r ) const
    {
        return l.data() < r.data() ;
    }
};
int main()
{
    set<MyClass , MyClassLess > s;
    s.insert( MyClass(1) );
    s.insert( MyClass(3) );
    s.insert( MyClass(2) );
    s.insert( MyClass(1) );
    return 1;
}

当然,谁说不能自己写呢,不过,这样的话,就必须在声明的时候,显示指定比较类了。

三种方式,语言的使用上利用不同的知识点,但是,结果是完全相同的。在实际使用中,或许因为项目,代码等等诸多原因,不一定每种方法都适用,但是总应该有一种能够满足你的要求。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/winterTTr/archive/2010/04/23/5519045.aspx

转载于:https://www.cnblogs.com/Ray8686/archive/2011/03/01/1968289.html

STL学习笔记 ---- 由set的声明所引发的自定义比较的实现方式 作者:winterTTr(转载请注明)...相关推荐

  1. C++ STL学习笔记(3) 分配器Allocator,OOP, GP简单介绍

    继续学习侯捷老师的课程! 在前面的博客<C++ STL学习笔记(2) 容器结构与分类>中介绍了STL中常用到的容器以及他们的使用方法,在我们使用容器的时候,背后需要一个东西支持对内存的使用 ...

  2. C++ STL学习笔记

    C++ STL学习笔记一 为何要学习STL: 数据结构与算法是编程的核心,STL中包含各种数据结构和优秀的算法,确实值得深入学习,本文中虽然着重使用,但希望有心的朋友能多看看相关数据结构的实现,对于C ...

  3. C++STL学习笔记(4) 分配器(Allocator)

    在前面的博客<C++ STL学习笔记(3) 分配器Allocator,OOP, GP简单介绍>中,简单的介绍了分配器再STL的容器中所担当的角色,这一节对STL六大部件之一的分配器进行详细 ...

  4. QT学习笔记(七):定时器事件的3种常用使用方式

    QT学习笔记(七):定时器事件的2种常用使用方式 Qt中定时器的使用有2种方法:一种是使用QObject类提供的定时器通过重载 timerEvent 事件处理过程函数,一种就是使用QTimer类. 其 ...

  5. WPF学习笔记(7):DataGrid中数字自定义格式显示

    WPF学习笔记(7):DataGrid中数字自定义格式显示 原文:WPF学习笔记(7):DataGrid中数字自定义格式显示 DataGrid中数据显示如下图,数据格式比较杂乱.希望达到以下要求:(1 ...

  6. Spring Security技术栈学习笔记(十四)使用Spring Social集成QQ登录验证方式

    上一篇文章<Spring Security技术栈开发企业级认证与授权(十三)Spring Social集成第三方登录验证开发流程介绍>主要是介绍了OAuth2协议的基本内容以及Spring ...

  7. 片上总线Wishbone 学习—— 转载请注明出处:http://blog.csdn.net/ce123

    片上总线Wishbone 学习(零)前言 声明:版权所有,欢迎转载! 转载请注明出处:http://blog.csdn.net/ce123 为了更加升入的理解片上系统,比如S3C2440等,今天开始学 ...

  8. 特此郑重声明!我的文章全部是原创作品!转载请注明出处!

    特此郑重声明! 我的帖子全部是原创作品!转贴请注明出处!如有任何问题或不解,请给我发邮件:yang.yang@jado.cn 或者通过msn:seeblue1981@hotmail.com联系我!有什 ...

  9. 【C++ STL学习笔记】C++ STL序列式容器(array,vector,deque,list)

    文章目录 C++ STL容器是什么? 迭代器是什么,C++ STL迭代器(iterator)用法详解 迭代器类别 迭代器的定义方式 C++序列式容器(STL序列式容器)是什么 容器中常见的函数成员 C ...

最新文章

  1. c/c++获取文件大小的方法
  2. 提前“剧透”能提高自监督学习性能吗?华为诺亚实验室说:不一定!
  3. 任意整数分频(图文并茂)
  4. word域变成正常文本_超级干货|最全的PPT、Excel、Word实用宝典,助你办公效率翻倍!...
  5. iis管理常用命令 创建IIS站点 应用应用程序 及虚拟目录
  6. Oracle发布更新使数据库性能优化达到75%
  7. python 打开pdf文件_Python3检验pdf文件是否有效
  8. Scrapy 爬虫框架初体验三 —— 工程优化及其完善
  9. 【喜报】2016 年度最受欢迎中国开源软件TOP20出炉——JEECG、JEEWX双入围!
  10. django-反向解析-命名分组路由的反解
  11. 国家邮政局:对刷单、贩卖快递盲盒等进行清理整顿
  12. STM32单片机实现DMA+ADC+UART功能
  13. LeetCode 260. Single Number III
  14. mysql主从复制与主主复制
  15. 地图投影和矢量瓦片详解
  16. duilib开发(十二):使用自定义控件
  17. 根据经纬度计算两点之间的距离
  18. 计算机音乐狂浪乐谱,当代歌曲 - 听海(流行歌曲 简谱)
  19. 蓝牙低功耗音频技术 -- 1 背景和遗产
  20. 晶体二极管工作原理(详解)

热门文章

  1. 用数据说话,基金经理一年到底能挣多少钱?
  2. idea中新建.xml文件找不到选项的解决方法
  3. mybatis基础总结02 -配置详解
  4. flex4.5的DataGrid
  5. php 把查询数据转json格式,php将从数据库查询到的数据转化为json格式,并写入json文件中...
  6. python | while循环与for循环 | 循环嵌套 | pass通用类型,循环整体结束或开始下一轮循环
  7. python的类是什么_Python类(class)
  8. jQuery HTML操作
  9. 如何快速转载CSDN博客(详细)
  10. 数据结构实验 3.抓住那头牛