【问题标题】:C++ trouble sorting a vector of custom objectsC++ 对自定义对象向量进行排序时遇到问题
【发布时间】:2014-06-13 09:19:21
【问题描述】:

编辑,更新:很好的答案谢谢大家。我已经为 removeDup(vector<Graph::Vertex>&); 函数中。

我有一个需要从中删除重复项的对象向量,但我收到一个我不熟悉的错误(错误如下)。这是一个非常简单的对象,公开包含在一个名为 Graph 的类中:

struct Vertex
    {
        string name;
        int num;
    public:
        Vertex();
        Vertex(string, int);
        void printVertex();
    };

我已经阅读了一些关于此的主题 (This one in particular) 但是当我尝试使用 unique 对向量进行排序时,我遇到了一个非常奇怪的错误。

我使用push_back添加到向量:

vector<Graph::Vertex> v;
Graph::Vertex first(string1, count);
v.push_back(first);

并尝试使用我在另一个线程中找到的这段代码进行排序:

void removeDup(vector<Graph::Vertex> v)
{
    sort( v.begin(), v.end());
    v.erase( unique( v.begin(), v.end() ), v.end() );
}

但是,当我使用这个功能时,我得到一个错误:

error C2678: binary '==' : no operator found which takes a left-hand operand of type 'Graph::Vertex' (or there is no acceptable conversion)

我对 C++ 编程有点陌生,不知道为什么会发生这个错误,或者它意味着什么。有人可以解释为什么我会收到这个错误吗?我是否需要编写一个运算符重载函数来处理它?

非常努力地谷歌(并使用这个网站)来解决这个错误,但最后不得不在这里发表我的第一篇文章寻求帮助。注意:这是一个家庭作业,所以我决定不包含我的其余代码以避免被勺子喂答案,但如果我没有提供足够的信息,请告诉我。

【问题讨论】:

    标签: c++ sorting object vector duplicates


    【解决方案1】:

    std::sort 和std::unique 都需要比较项目才能完成工作。不过它们有一些不同的要求:std::unique 比较相等,std::sort 比较排序。对于您的情况,一个明显的可能性是按此一般顺序编写代码:

    bool operator==(Vertex const &other) const {
        return num == other.num;
    }
    
    bool operator<(Vertex const &other) const {
        return num < other.num;
    }
    

    [注意:这些将是您的 Vertex 类的成员函数。]

    可以通过其他方式实现所需的功能,特别是如果(例如)您可能希望有时根据一个字段对对象进行排序,而在其他时间根据另一个字段排序(例如,按数字排序和按名称排序,对于您的 Vertex 类)。

    您可以通过将第三个参数传递给sort 和/或unique 来告诉它使用什么来进行比较。至少在当前的 C++ 中,如果我要这样做,我一般会使用 lambda 表达式来指定比较:

    std::sort(v.begin(), v.end(),
        [](Vertex const &a, Vertex const &b) { return a.name < b.name; });
    

    这会将比较代码放在排序旁边,因此很容易看到您是如何进行排序的。您可以改用单独的函数或函数对象,但这样做意味着您需要注意名称以确保它描述了排序顺序:

    struct by_name {
        bool operator()(Vertex const &a, Vertex const &b) const {
            return a.name < b.name;
        }
    };
    
    // ...
    std:sort(v.begin(), v.end(), by_name());
    

    【讨论】:

    • 精彩的解释!非常感谢
    【解决方案2】:
    • 当需要排序时,编译器不知道哪个 Vertex 放在另一个 Vertex 之前。你需要告诉编译器这个信息。因此使用 3 参数 std::sort() 函数,或者为您的 Vertex 类编写一个重载的 operator &lt;。

    • 编译器不知道是什么让一个顶点等于另一个顶点。你需要告诉编译器这个信息。因此使用 3 参数 std::unique() 函数,或者为您的 Vertex 类编写一个重载的 operator ==。

    • 通过引用传递向量等对象,而不是通过值:

      void removeDup(vector&lt;Graph::Vertex&gt;&amp; v)

    注意&amp;。

    【讨论】:

      【解决方案3】:

      两个识别唯一的对象,您需要能够测试是否相等(毕竟,您将如何识别相同的对象)。

      假设有两个对象a 和b。测试相等性的规范方法是a == b。如果您对ints 进行操作,编译器就知道如何处理这个表达式(例如发出CMP 指令)。

      但是,由于您自己定义了Vertex,因此必须告诉编译器如何将两个顶点视为相等。定义算术运算符的最简单方法如下:

      struct Vertex
      {
          string name;
          int num;
      public:
          Vertex();
          Vertex(string, int);
          void printVertex();
      
          friend bool operator==(Vertex const& lhs, Vertex const& rhs)
          { return lhs.num == rhs.num; } // or whatever you wish to do here
      };
      

      请注意:在定义 == 时,您可能还希望定义 != 以保持一致。您还可能希望定义所有&lt;、&lt;=、&gt;、&gt;=,以便进行比较...

      【讨论】:

        【解决方案4】:

        编译器在尝试排序时不知道如何将一个顶点对象与另一个进行比较。您可以通过在 Vertex 类中重载

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多