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

看一个问题

看下面这段代码

// 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;
}
posted @ 2021-11-21 00:03  徐摆渡  阅读(859)  评论(0编辑  收藏  举报