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

对于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

posted on 2011-03-01 20:15  Ray_8686  阅读(274)  评论(0编辑  收藏  举报