通过引用从std :: vector删除节点

时间:2014-03-31 06:36:44

标签: c++ stdvector

我对C ++比较陌生,所以请原谅任何疏忽。

我有一个包含id和位置的自定义Node类。在我的代码的主要部分,我创建了一个向量std::vector<Node>candidateNodes,并在其中推送了一堆新创建的节点。

我有一个函数expandCandidateNode,它接受来自candidateNodes向量的一个节点以及向量本身并用它做一些事情:

expandCandidateNode(Node &candidateNode, std::vector<Node> &candidateNodes)

在函数结束时,我想从candidateNodes向量中删除candidateNode。我尝试使用this stackoverflow question中的解决方案,看起来像这样:

candidateNodes.erase(std::remove(candidateNodes.begin(), candidateNodes.end(), candidateNode), candidateNodes.end());

但是,当我尝试构建项目时,出现以下错误:

1>c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\algorithm(1815): error C2678: binary '==' : no operator found which takes a left-hand operand of type 'Node' (or there is no acceptable conversion)

我仔细看了一下,发现错误源自算法类中的模板函数remove。我不确定从这里做什么。我的目的是让candidateNodes向量搜索与candidateNode具有相同引用的节点(基本上确保它们是内存中的相同对象),并将其删除,但似乎==运算符无法比较它们参考?我可能误会了什么。如果有人可以澄清我如何从矢量中正确地删除节点,给定它的参考,我将非常感激。谢谢。

3 个答案:

答案 0 :(得分:1)

std::remove有两种形式:

您使用的std::remove将值作为第三个参数,并使用等于运算符==将其与元素进行比较。您的Node类似乎不支持这些比较,因此您可以在标准库的内部深处获得错误,进行比较。

替代方案是std::remove_if。而不是要比较的值,它需要一个可调用的第三个参数。它将范围内的对象传递给可调用对象,并期望结果可转换为bool,以判断是否应该删除该元素。

因此,如果您希望Node==具有可比性,则必须定义该运算符,然后才能使用std::remove

bool operator== (Node const& lhs, Node const& rhs) {
  return lhs.id == rhs.id && lhs.position == rhs.position;
}

正如你所说的那样只需致电remove

另一个选择是向std::remove_if提供一个函数对象。这可以通过C ++ 11 lambda表达式,或者通过在C ++ 03中提供手写的函子来完成:

<强> C ++ 11:

candidateNodes.erase (
  std::remove_if (
    candidateNodes.begin(), 
    candidateNodes.end(), 
    //here comes the C++11 lambda:
    [&](Node const& node) {
      return node.id == candidateNode.id && node.position == candidateNode.position;
    }
  ), 
  candidateNodes.end()
);   

C ++ 03:

struct cmpNode {
  Node const& candidateNode;

  cmpNode(Node const& cn) : candidateNode(cn) {}

  bool operator()(Node const& node) {
    return node.id == candidateNode.id && node.position == candidateNode.position;
  }
};

candidateNodes.erase(
  std::remove_if(
    candidateNodes.begin(), 
    candidateNodes.end(), 
    //here comes the C++03 functor:
    cmpNode(candidateNode);
  ), 
  candidateNodes.end()
);   

答案 1 :(得分:0)

你可以这样做,

 struct Node
    {
            int id;
            int position;
        };

        struct Node targetNode; //the node you want to move
        bool comp(const Node& element)
        {
            return ((element.id == targetNode.id) && (element.position == targetNode.position));
        }
        candidateNodes.erase(std::remove_if(candidateNodes.begin(), candidateNodes.end(), comp), candidateNodes.end());

答案 2 :(得分:0)

std::remove使用operator==进行检查。 您仍然需要将此运算符添加到Node类。

我建议您依靠Nodeid和/或position的唯一数据创建运营商的良好实施。