• 从优先队列中重载小于号谈起


    看一个问题

    看下面这段代码

    // cpp
    struct node {
        int a, b;
        bool operator< (const node& x) {
            return a > x.a;
        }
    };
    int main()
    {
        priority_queue<node> pq;
        pq.push(node{1, 2});
        return 0;
    }
    

    代码意图声明一个结构体并重载小于号,以使用优先队列维护

    但是过不了编译,部分报错信息如下

    报错信息

    追踪

    看一下 /usr/include/c++/6/bits/stl_function.h:386:20 指向的代码

    // cpp
    template<typename _Tp>
    struct less : public binary_function<_Tp, _Tp, bool>
    {
        _GLIBCXX14_CONSTEXPR
        bool
        operator()(const _Tp& __x, const _Tp& __y) const
        { return __x < __y; }
    };
    

    可以看到 less() 这个函数对象 (function object) 重载了 () 运算符,接收两个 const 类型的参数

    而在 cpp 里面,只有 const 成员函数才能够被 const 对象调用

    这是编译器为了保证成员函数不会修改 const 对象的成员变量,所做出的强制要求

    解决

    解决方法很简单,把重载运算符的函数声明为 const 即可

    // cpp
    struct node {
        int a, b;
        bool operator< (const node& x) const {
            return a > x.a;
        }
    };
    int main()
    {
        priority_queue<node> pq;
        pq.push(node{1, 2});
        return 0;
    }
    

    为优先队列重载小于号的四种办法

    给定结构体

    // cpp
    struct node {
        int a, b;
    };
    
    int main()
    {
        priority_queue<node> pq;
        pq.push(node{1, 2});
        return 0;
    }
    

    为它重载小于号,以支持优先队列来维护它

    在类内声明成员函数

    声明为 const 的成员函数,输入参数也得是 const

    // cpp
    struct node {
        int a, b;
        bool operator< (const node& x) const
        {
            return a > x.a;
        }
    };
    int main()
    {
        priority_queue<node> pq;
        pq.push(node{1, 2});
        pq.push(node{2, 3});
        cout << pq.top() << endl; // 输出: 1 2
        return 0;
    }
    

    考虑一个简单的声明

    const node A{1, 2};
    const node B{3, 4};
    

    那么有如下等价的语句

    (A < B) <=> A.operator< (B)
    

    因此一切变得可以理解起来了

    • 由于是 const 对象的比较,所以声明为 const member function
    • 由于传入的参数也是 const 对象,所以成员函数的参数也要设置为 const,以扩大接受对象的范围

    在类内声明为友元函数

    // cpp
    struct node {
        int a, b;
        friend bool operator< (const node& x, const node& y)
        {
            return x.a > y.a;
        }
    };
    
    int main()
    {
        priority_queue<node> pq;
        pq.push(node{1, 2});
        pq.push(node{2, 3});
        cout << pq.top() << endl; // 输出: 1 2
        return 0;
    }
    

    友元函数虽然定义在类内,但是不是类的成员函数,只是具有类成员变量的访问权

    在类外重载小于号

    // cpp
    struct node {
        int a, b;
    };
    
    bool operator< (const node& x, const node& y)
    {
        return x.a > y.a;
    }
    
    int main()
    {
        priority_queue<node> pq;
        pq.push(node{1, 2});
        pq.push(node{2, 3});
        cout << pq.top() << endl; // 输出: 1 2
        return 0;
    }
    

    声明新的函数对象

    // cpp
    struct node {
        int a, b;
        friend ostream& operator<< (ostream& out, const node& x) {
            out << x.a << ' ' << x.b;
        }
    };
    struct cmp {
        bool operator() (const node& x, const node& y) {
            return x.a > y.a;
        }
    };
    
    int main()
    {
        priority_queue<node, vector<node>, cmp> pq;
        pq.push(node{1, 2});
        pq.push(node{2, 3});
        cout << pq.top() << endl; // 输出: 1 2
        return 0;
    }
    
  • 相关阅读:
    VB运算符总结
    动态实现树形菜单
    使用C#开发ActiveX控件
    jquery+ajax加载xml文件到页面
    C#序列化与反序列化
    jquery之ajax——全局事件引用方式以及各个事件(全局/局部)执行顺序
    SerialPort实现对串口COM的操作(有些纠结)
    jquery+ajax+C#实现无刷新操作数据库数据
    超过一百多个Web2.0在线生成器
    asp.net URL Rewriter 问题
  • 原文地址:https://www.cnblogs.com/ChenyangXu/p/15583108.html
Copyright © 2020-2023  润新知