简体   繁体   English

C++ - std::list.erase() 不删除元素

[英]C++ - std::list.erase() not removing element

I am having a small issue with a bit of code for a school assignment (I know that's shunned upon here, but I locked myself into using the std::list library and am paying for it).我在学校作业的一些代码方面遇到了一个小问题(我知道这里避开了这一点,但我将自己锁定在使用std::list库并为此付费)。 I have a function that has a list of pointers to classes passed into it along with a particular ID belonging to one of those classes that I want to destroy and resize my list.我有一个函数,其中包含一个指向传递给它的类的指针列表,以及一个属于我想要销毁和调整列表大小的类之一的特定 ID。 However, with my code, the list is never resized and the values are garbage, that crash my program.但是,使用我的代码,列表永远不会调整大小并且值是垃圾,这会导致我的程序崩溃。 So it looks like the actual class is being removed, but the element is never removed from the list...所以看起来实际的类正在被删除,但元素永远不会从列表中删除......

If I had time to make my own doubly-linked list implementation, I'd iterate over the list looking for the element that I want to delete.如果我有时间实现自己的双向链表,我会遍历列表以查找要删除的元素。 If it is found, create a temporary node pointer and point that to the node I am about to delete.如果找到,则创建一个临时节点指针并将其指向我将要删除的节点。 Set the previous node's "next" element to the iterator's "next" element, and then delete the iterator node.将上一个节点的“next”元素设置为迭代器的“next”元素,然后删除迭代器节点。

But.. using the stl::list implementation, I'm at a loss what to do.但是.. 使用stl::list实现,我不知所措。 Here is what I have so far, where a DOCO is a class, and the elements in the list are pointers to instances of classes.这是我到目前为止所拥有的,其中 DOCO 是一个类,列表中的元素是指向类实例的指针。 I've looked into remove() vs. erase() , which maybe using both may fix it, but I'm not sure how to implement remove() with an iterator like this.我已经研究过remove()erase() ,可能两者都使用可以解决它,但我不确定如何使用这样的迭代器实现remove()

bool DOCO::kill_doco(std::list < DOCO* > docolist, int docoid)
{
    for (std::list<DOCO*>::iterator it = docolist.begin(); it != docolist.end(); )
    {
        if ((*it)->id == docoid)
        {
            delete * it;
            it = docolist.erase(it);
            std::cerr << "item erased\n";
        }
        else
        {
            ++it;
        }
    }
    std::cerr << "leaving kill\n";
    
    return true;
}
kill_doco(std::list < DOCO* > docolist

this creates a copy of the list.这将创建列表的副本 This copy is a list of pointers.这个副本是一个指针列表。

You proceed to modify the copy of the list, and delete an element in it.您继续修改列表的副本,并删除其中的一个元素。

The original list (which you copied) still has the original pointer, which is now pointing to a deleted object.原始列表(您复制的)仍然具有原始指针,该指针现在指向已删除的对象。

The easy fix is:简单的解决方法是:

kill_doco(std::list < DOCO* >& docolist

C++ is a value-oriented language, unlike languages like Java or C#. C++ 是一种面向价值的语言,与 Java 或 C# 等语言不同。 The name of something refers to an actual value of that thing, not a reference to it.事物的名称指的是该事物的实际价值,而不是对它的引用。

Pointers are similarly the value of the address of the object.指针同样是对象地址的值。

Reference like semantics, or pointer-like semantics, can be done in C++.类似引用的语义,或类似指针的语义,可以在 C++ 中完成。 But, unlike Java/C#, by default every object in C++ is an actual value.但是,与 Java/C# 不同的是,默认情况下,C++ 中的每个对象都是一个实际值。

People who move from one language to the other (either way) can get confused by this.从一种语言迁移到另一种语言(无论哪种方式)的人可能会对此感到困惑。

The "default" object type in a C++ program is a regular type -- a type that acts like an integer when you copy it around and the like. C++ 程序中的“默认”对象类型是常规类型——当你复制它时,这种类型就像整数一样。 It is relatively easy to move away from this, but that is the default.摆脱这一点相对容易,但这是默认设置。

So what you did was akin to:所以你所做的类似于:

void clear_bit( int x, int bit ) {
  x = x & ~(1 << bit);
}

and being surprised that the value x you passed in wasn't modified by the function.并惊讶于您传入的值x没有被函数修改。 The "dangling" pointer left in the original list is the 2nd thing that bit you.原始列表中留下的“悬空”指针是咬你的第二件事。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM