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

Removing a Node by reference from std::vector

本文关键字:vector 删除 节点 std 引用      更新时间:2023-10-16

我对C++相对较新,所以请原谅任何疏忽。

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

我有一个函数,expandCandidate Node,它从候选节点的向量以及向量本身中获取其中一个节点,并用它做一些事情:

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

在函数结束时,我想从候选节点向量中删除候选节点。我尝试使用这个堆栈溢出问题的解决方案,它看起来像这样:

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

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

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

我仔细观察了一下,发现错误源于算法类中的模板函数 delete。我真的不确定从这里开始做什么。我的目的是让 candidateNodes 向量搜索与 candidate Node 具有相同引用的节点(基本上确保它们是内存中的相同对象),并将其删除,但似乎 == 运算符无法比较它们的引用?我可能误解了什么。如果有人能澄清我如何正确从向量中删除节点,鉴于它的参考,将不胜感激。谢谢。

>std::remove有两种风格:

您使用的std::remove将值作为第三个参数,并使用相等运算符 == 将其与元素进行比较。您的Node类似乎不支持这些比较,因此您会在进行比较的标准库深处的某个地方遇到错误。

另一种选择是 std::remove_if .它不是要比较的值,而是将可调用对象作为第三个参数。它将范围内的对象传递给该可调用对象,并期望一个可转换为布尔值的结果,以告知是否应删除该元素。

因此,如果您希望您的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()
);   
你可以

这样做,

 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());

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

我建议您创建一个良好的运算符实现,依赖于Nodeid和/或position的唯一数据。