C++ 仅使用迭代器从列表中删除元素

C++ 仅使用迭代器从列表中删除元素,c++,list,iterator,std,C++,List,Iterator,Std,如果只有指向要删除元素的迭代器,是否可以从std::list中删除元素?我有大量的函数需要迭代器来列出元素,如果必须将拥有的列表传递给每个元素,这将是一个巨大的不便。编辑: 您不能使用单个迭代器 如果您有begin/end迭代器,您可以使用该算法将所有要擦除的元素移动到末尾,然后在稍后删除它们 如果您不这样做,或者您当前的设计无法实现上述功能,我建议更改您的函数以采用std::pair或类似的方式。不,这是不可能的。顾名思义,迭代器的工作是迭代序列的元素。检查一下C++标准库中迭代器设计的摘要。

如果只有指向要删除元素的迭代器,是否可以从
std::list
中删除元素?我有大量的函数需要迭代器来列出元素,如果必须将拥有的
列表
传递给每个元素,这将是一个巨大的不便。

编辑:

您不能使用单个迭代器

如果您有begin/end迭代器,您可以使用该算法将所有要擦除的元素移动到末尾,然后在稍后删除它们


如果您不这样做,或者您当前的设计无法实现上述功能,我建议更改您的函数以采用
std::pair
或类似的方式。

不,这是不可能的。顾名思义,迭代器的工作是迭代序列的元素。检查一下C++标准库中迭代器设计的摘要。< /P> < P>不,你不能。迭代器是根据指针建模的轻量级对象,不携带对它们所引用的容器的引用。(尽管有些实现在调试模式下在内部执行此操作。)


正如当您只有一个指向数组的指针时无法从数组中“删除”对象一样,您也无法在不访问容器的情况下从容器中删除对象

您可以手动执行此操作。迭代器将
\u M_节点
公开为当前节点。您可以执行以下操作:

itr._M_node->_M_prev->_M_next = itr._M_node._M_next;

标准库不能做到这一点,但可以使用Boost的入侵列表,它有这样一个界面。

虽然其他人提到你不能做到这一点,但我想我可以提供原因

我相信具体的技术原因(而不是设计原因)是列表做了一些维护,比如跟踪大小,这要求某些操作必须通过列表才能进行维护


正是由于这个原因,可能提供的任何黑客攻击都可能失败。

但它也需要列表。
std::remove()
函数不会从容器中移除项目,因为它无法。看看这本书。@André-我就是这么说的。使用它将它们移动到末尾,然后在稍后的时候删除它们。我决定做类似的事情,那就是在它所持有的项目中存储对所属列表的引用。该解决方案涉及对现有代码的最小更改(我认为有两行代码)。但是如果我不能做到这一点,我会按照这个答案中的建议去做(std::pairone),所以我会把这个标记为答案。虽然这在原则上是正确的(我已经投票了),但是请注意,
std::remove()
不一定会将要删除的对象移动到最后。它没有对他们的遭遇提出任何要求。对于
std::vector
,我确信所有的实现都会覆盖它们。对于
std::list
我不确定。请注意,以这种方式使用迭代器不利于将其用作设计模式,但这并不是说在许多情况下(例如,查看集合的元素)这样做是不对的。@Jeremy:实际上,迭代器不再用作设计模式。然而,它在迭代器失效方面的语义较差。在许多容器中,删除一个项会使所有迭代器失效,包括您当前用于对元素进行迭代的迭代器。@Andre是的,但我总是使用一个
列表
,如果您从中删除一个项,它不会使其他迭代器失效。另外@nj,我认为这与这个问题无关。因为
list
是一个双链接列表,您能否编写一个函数来操纵
next
previous
指针,从而删除元素?还是真的很糟糕?还是仅仅因为成员是私人的?@Seth:是的,这在技术上是可能的。例如,在Java中,迭代器有一个。但是,这不是C++迭代器设计的一部分。我想标准委员会倾向于与其他容器保持一致。@Seth:这可能是针对特定供应商库的特定版本。然而,这意味着大量的非标准(而且肯定是不可移植的)代码。此外,成员可能是私有的。这只是特定实现的特定版本中特定容器中的特定迭代器的情况,这是一个实现细节,甚至可以通过使用正确的预处理器令牌来关闭。此外,它可能会弄乱容器的内部结构,您需要知道这一点。更不用说您没有更新
\u M\u next
\u prev
指针(因为它是一个链接列表)。这是我一直在想的,但是这段代码也需要与不同的版本/编译器一起工作。请注意,即使这是可能的,这也会导致内存泄漏。您还需要访问容器的分配器来释放内存,如果列表被缓存,您还需要减少列表的项计数(标准允许实现在O(1)
size()
和O(1)
splice()
之间进行选择)。这是一个好主意,尽管看起来你可以让迭代器告诉他们的父列表他们正在删除他们自己或者其他什么。