我在 C++ 程序中有一个 std::list,其中包含 A 类的对象。
假设我里面有 10 个物体。我有一个对存储的第 6 个对象的引用,在另一个数据结构中,例如 ref_6。假设我需要从列表中删除第八个元素。为此,我将使用 pop_front 8 次并将 8 个对象存储在向量中,并使用 push_front 7 次将前 7 个元素插入到列表中,因此现在我的结果列表将包含 9 个元素。现在,当我尝试访问存储在 ref_6 中的对象(第 6 个元素)时,我无法执行此操作。该参考文献中有一些垃圾值。
我假设当我执行弹出和推送时,同一对象的内存位置会发生变化。我该如何处理这个问题?
I have a std::list in a C++ program, which contains objects of a Class A.
Lets say I have 10 objects in it. I have a reference to the 6th object stored, in another data structure say ref_6. Lets say I need to remove the 8th element from my list. To do this, I would use pop_front 8 times and store 8 objects in a vector and use push_front 7 times to insert the first 7 elements back in the list so now my resulting list would have 9 elemnts. Now i when i try to access the object stored in ref_6 , which was the 6th element , I cant do it. There is some garbage value in this reference.
I am assuming that when i do a pop and a push, the memory location of the same object changes . How do I deal with this ?
发布评论
评论(4)
为什么要用这样的方式删除东西? D:这不是一个堆栈。列表的全部要点(并且唯一点*)是您可以在恒定时间内删除任何元素。 (虽然发现它是线性的。)
只要这样做:
并且没有其他迭代器失效。 (事实上,删除一个元素会使对它的任何引用无效。)
*您可能甚至不应该使用列表。对于学习数据结构来说,列表很好,但它们非常糟糕。
Why would you erase things in such a manner? D: It's not a stack. The entire point (and only point*) of a list is that you can remove any element in constant time. (Though finding it is linear.)
Just do this:
And no other iterators are invalidated. (Indeed, erasing an element invalidates any references to it.)
*You probably shouldn't even be using a list. Lists are nice when it comes to learning data structures, but they're pretty awful.
列表将其元素存储在不连续的内存块中,当从列表中删除元素时,这些内存块会被释放。因此,引用(简单地实现为指针)指向内存已被释放的元素。
从列表中删除给定元素的更简单方法是获取指向它的迭代器并使用方法
std::list::iterator = /*以某种方式获取第 8 个元素的迭代器*/
yourList.erase(8th_element_iterator);
:
第一步(获取第 8 个元素的迭代器)可以通过获取列表开头的迭代器并将其向前推进 7 个位置来
完成
std::list::iterator first_iter = yourList.begin();
std::list::iterator 8th_iter = std::advance(first_iter, 7);
The list stores its elements in discontinous chunks of memory that get freed when the element is removed from the list. So the reference ( which is implemented simply as a pointer ) points to an element whose memory has been already freed.
Easier way to remove a given element from the list is to get the iterator pointing to it and use method
std::list::iterator = /*somehow get the iterator to the 8th element*/
yourList.erase(8th_element_iterator);
The first step ( getting the iterator to the 8th element ) can be done for example by getting the iterator of the begininning of the list and advancing it 7 positions forward:
std::list::iterator first_iter = yourList.begin();
std::list::iterator 8th_iter = std::advance(first_iter, 7);
这里有些可疑...您正在按值将
T
类型的对象存储在std::list
中。您可以在其他地方保留对这些对象的引用。这是正确的吗?如果是,我看到几个问题...列表的许多操作可能会使存储的引用无效,因为std::list
仅保证元素值的顺序类型为T
。如果您想在多个位置存储对这些元素的引用,请使用std::tr1::shared_ptr
和std::list; >
。然后,您可以安全地删除或添加(甚至重新定位)列表中的元素,并且保留在其他位置的引用仍然有效。请注意存储std::listiterators
,问题是一样的。Something smells fishy here... You are storing object of type
T
in astd::list<T>
by value. You keep references to those objects in other places. Is that correct? If yes, I see several problems... Many manipulations of lists might invalidate stored references, sincestd::list<T>
only guarantees a sequential order of values of elements of typeT
. If you want to store references to those elements in several places usestd::tr1::shared_ptr<T>
andstd::list<std::shared_ptr<T> >
. Then, you can safely remove or add (even reposition) elements in your list and the references kept in other places remain valid. Beware of storingstd::list<T>iterators
, the problem would be the same.我指的是你的回复。抱歉,我没搞清楚账号...
请考虑以下几点:
要点是; > 相反!
A
的实例是按值存储的(=复制的),因此您所做的事情本质上是不安全的。使用 std::listI am referring to your response. Sorry, I didn't get the account thing right...
Please consider the following:
The point is that instances of
A
are stored by value (= copied), so what you are doing is inherently unsafe. Usestd::list<std::tr1::shared_ptr<A> >
instead!