【问题标题】:Why is const required for 'operator>' but not for 'operator<'?为什么 'operator>' 需要 const 而 'operator<' 不需要?
【发布时间】:2018-07-30 10:10:16
【问题描述】:

考虑这段代码:

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;

struct MyStruct
{
    int key;
    std::string stringValue;

    MyStruct(int k, const std::string& s) : key(k), stringValue(s) {}

    bool operator < (const MyStruct& other) {
        return (key < other.key);
    }
};

int main() {
    std::vector < MyStruct > vec;

    vec.push_back(MyStruct(2, "is"));
    vec.push_back(MyStruct(1, "this"));
    vec.push_back(MyStruct(4, "test"));
    vec.push_back(MyStruct(3, "a"));

    std::sort(vec.begin(), vec.end());

    for (const MyStruct& a : vec) {
        cout << a.key << ": " << a.stringValue << endl;
    }
}

它编译得很好,并给出了预期的输出。但如果我尝试按降序对结构进行排序:

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;

struct MyStruct
{
    int key;
    std::string stringValue;

    MyStruct(int k, const std::string& s) : key(k), stringValue(s) {}

    bool operator > (const MyStruct& other) {
        return (key > other.key);
    }
};


int main() {
    std::vector < MyStruct > vec;

    vec.push_back(MyStruct(2, "is"));
    vec.push_back(MyStruct(1, "this"));
    vec.push_back(MyStruct(4, "test"));
    vec.push_back(MyStruct(3, "a"));

    std::sort(vec.begin(), vec.end(), greater<MyStruct>());

    for (const MyStruct& a : vec) {
        cout << a.key << ": " << a.stringValue << endl;
    }
}

这给了我一个错误。 Here is the full message:

/usr/include/c++/7.2.0/bits/stl_function.h:在 'constexpr bool std::greater<_tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = MyStruct]':
/usr/include/c++/7.2.0/bits/stl_function.h:376:20:错误:“operator>”不匹配(操作数类型为“const MyStruct”和“const MyStruct”)
{ 返回 __x > __y; }

似乎是因为这里的这个函数没有const 限定符:

bool operator > (const MyStruct& other) {
        return (key > other.key);
}

如果我添加它,

bool operator > (const MyStruct& other) const {
        return (key > other.key);
}

然后一切又好了。为什么会这样?我对运算符重载不太熟悉,所以我只是把它放在内存中,我们需要添加const,但是为什么它在没有const 的情况下适用于operator&lt; 仍然很奇怪。

【问题讨论】:

标签: c++ sorting operator-overloading


【解决方案1】:

你会得到不同的行为,因为你实际上是在调用两个不同的(重载的)sort 函数。

在第一种情况下,您调用两个参数std::sort,它直接使用operator&lt;。由于向量元素的迭代器会产生非常量引用,因此它可以应用 operator&lt; 就好了。

在第二种情况下,您使用的是std::sort 的三参数版本。接受函子的那个。你通过std::greater。该函子有一个operator(),声明如下:

constexpr bool operator()( const T& lhs, const T& rhs ) const;

注意 const 引用。它将需要比较的元素绑定到 const 引用。所以你自己的operator&gt; 也必须是正确的。

如果你用std::less 调用std::sort,你的operator&lt; 会产生同样的错误,因为它不是常量正确的。

【讨论】:

  • 吹毛求疵:std::less&lt;void&gt; 除外。
【解决方案2】:

std::sort(vec.begin(), vec.end()) 的使用仅取决于operator&lt; 函数。它不要求该函数能够与const 对象一起使用。

另一方面,std::greater 要求函数能够使用 const 对象。

如果你使用std::less,你会看到类似的问题,比如std::sort(vec.begin(), vec.end(), std::less&lt;MyStruct&gt;())


话虽如此,operator&lt; 函数和operator&gt; 函数没有理由成为非const 成员函数。任何不修改成员数据的成员函数都应该成为const成员函数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-23
    • 1970-01-01
    相关资源
    最近更新 更多