标准库排序和用户定义类型

时间:2009-07-25 04:54:46

标签: c++

如果我想通过它所拥有的两种变量之一对UDT的向量进行排序,标准库排序是否可以执行此操作,或者我是否需要编写自己的排序函数。

例如,如果你有

struct MyType{
 int a;
 int b;
};

vector<MyType> moo;

// do stuff that pushes data back into moo

sort(moo.begin(), moo.end()) // but sort it by lowest to highest for a, not b

这样可以使用stdlib排序吗?感谢。

2 个答案:

答案 0 :(得分:11)

如果类型实现"bool operator < (...) const"和复制构造函数(编译生成或自定义),则可以使用标准函数。

struct MyType {
    int a;
    int b;
    bool operator < (const MyType& other) const {
        ... // a meaningful implementation for your type
    }
    // Copy constructor (unless it's a POD type).
    MyType(const MyType &other)
        : a(other.a), b(other.b) { }
    // Some other form of construction apart from copy constructor.
    MyType()
        : a(0), b(0) { }
};

或者,您可以将排序函数(或仿函数)作为第三个参数传递给sort(),而不是实现运算符"<"

bool type_is_less(const MyType& t1, const MyType& t2) { ... }
...
std::sort(c.begin(), c.end(), type_is_less);

这在以下情况下很有用:

  1. 您不希望出于任何原因实现运算符"<"
  2. 您需要对内置或指针类型的容器进行排序,您不能为其重载运算符。
  3. 您希望使用不同的顺序对序列进行排序。例如:有时你想要一个带名字/名字的成员按名字排序的结构,其他时间用姓氏排序。两个不同的函数(或仿函数)使这些选项变得微不足道。

答案 1 :(得分:4)

有三种方法可以做到这一点:

您可以为您的班级重载operator<

bool operator<(const MyType& lhs, const MyType& rhs) {return lhs.a<rhs.a;}

这样做的缺点是,如果你想根据b对它们进行排序,那你就不走运了。

您还可以为您的类型专门设置std::less。这使得std::sort工作(以及其他一些事情,比如在地图中使用类型作为键)而不会劫持operator<这个含义。但是,它仍会劫持a的通用比较语法,而您可能会在代码中的其他位置根据b比较您的类型。

或者您可以像这样编写自己的比较器:

struct compare_by_a {
  bool operator()(const MyType& lhs, const MyType& rhs) const
  {return lhs.a<rhs.a;}
};

(注意:运算符之后的const并不是绝对必要的。但我仍然认为它的风格很好。)这使得通用的比较方法不明确;因此,如果某些代码想要在不知道的情况下使用它们,则编译会发出错误并让您意识到它。您可以选择性地明确地使用此比较器或其他比较器,无论您需要进行比较。