【问题标题】:Delete list element from class从类中删除列表元素
【发布时间】:2014-05-08 14:31:09
【问题描述】:

我尝试删除列表元素,但总是收到错误消息。

首先我有这个类结构:

Class X
{ public:
  ID;
  name;
}

然后我有列表容器。

现在,我想从容器中删除特定元素。

void delete ( list<X> a , X b )
{

list<X>::iterator itr;

for ( itr =a.begin() ; itr != a.end() ; itr++ )
{
    if ( *itr.ID == b.ID )
    { a.erase(itr) ; }
}
}

但是,我得到错误:

“迭代器没有 ID”。

我该如何解决?

【问题讨论】:

  • 一旦你解决了这个问题,你必须为函数找到一个新的名字,因为delete是一个关键字。 eraseremove 是常见的选择。您还需要通过引用传递a,并记住迭代器失效规则。或者你可以让生活更轻松并使用a.remove(b);
  • @MikeSeymour 你的意思是通过引用传递a
  • @bolov:确实如此。已更正。
  • @MikeSeymour 那应该是a.remove_if( [&amp;]( X const&amp; x ) { return x.ID == b.ID; } );,不是吗?
  • @JamesKanze:你说得对,我应该避免在没有先编译的情况下提出快速建议。

标签: c++ list erase


【解决方案1】:

这是因为点运算符. 比解引用运算符*“更强”。根据this table,点的优先级为2,而取消引用星号*的优先级为3(越低越强)。这意味着如果没有括号,编译器会尝试获取迭代器的成员ID,然后取消引用ID 的值。这是不可能的,因为迭代器没有名为 ID 的成员。

您需要用括号来强制执行您想要的优先级:

if ( (*itr).ID == b.ID )

或者,您可以使用-&gt; 运算符取消对迭代器的引用:

if ( itr->ID == b.ID )

注意:C++ 标准库提供了一种无需循环的方法:

a.erase(
    remove_if(
        a.begin()
    ,   a.end()
    ,   [](X x){ return x.ID == b.ID; }
    )
,   a.end()
);

Demo on ideone.

【讨论】:

  • /tmp/ccOJ9JuT.o: 在函数delete(std::list&lt;X, std::allocator&lt;X&gt; &gt;, X)': a.cpp:(.text+0x0): delete(std::list >, X)' 多重定义现在,我得到这个错误。但是,我从我的代码中删除了这个函数,主运行正确。
  • @ort23 您需要重命名您的delete 函数,它是一个保留名称。
  • @ort23 这很奇怪。你在头文件中定义了你的函数吗?
  • @ort23 这就是问题所在。您应该在标题中声明它(即void erase( list&lt;X&gt; a , X b );delete 函数的新名称)并在 CPP 文件中定义它。否则,每次在 CPP 文件中包含标头时,都会有重复的定义。
  • 他仍然会遇到问题:擦除迭代器指向的元素会使迭代器无效,因此他的循环将无法工作。
【解决方案2】:

我更喜欢使用 itr->ID 而不是 *itr.ID。后者有时会有点混乱。

【讨论】:

  • 不只是令人困惑;正如问题所说,没有括号,这是错误的。
猜你喜欢
  • 1970-01-01
  • 2017-03-05
  • 2014-12-19
  • 2013-11-25
  • 1970-01-01
相关资源
最近更新 更多