C++ 的问题容器

发布于 2024-09-17 22:03:24 字数 300 浏览 1 评论 0 原文

我在 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 ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

乖乖哒 2024-09-24 22:03:24

为什么要用这样的方式删除东西? D:这不是一个堆栈。列表的全部要点(并且唯一点*)是您可以在恒定时间内删除任何元素。 (虽然发现它是线性的。)

只要这样做:

typedef std::list<T> list_type;

list_type mylist; // populate it

list_type::iterator iter =  mylist.begin();
std::advance(iter, 8); // move to 8th item

mylist.erase(iter); // erase it

并且没有其他迭代器失效。 (事实上​​,删除一个元素会使对它的任何引用无效。)


*您可能甚至不应该使用列表。对于学习数据结构来说,列表很好,但它们非常糟糕。

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:

typedef std::list<T> list_type;

list_type mylist; // populate it

list_type::iterator iter =  mylist.begin();
std::advance(iter, 8); // move to 8th item

mylist.erase(iter); // erase it

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.

勿忘心安 2024-09-24 22:03:24

列表将其元素存储在不连续的内存块中,当从列表中删除元素时,这些内存块会被释放。因此,引用(简单地实现为指针)指向内存已被释放的元素。

从列表中删除给定元素的更简单方法是获取指向它的迭代器并使用方法


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

只有影子陪我不离不弃 2024-09-24 22:03:24

这里有些可疑...您正在按值将 T 类型的对象存储在 std::list 中。您可以在其他地方保留对这些对象的引用。这是正确的吗?如果是,我看到几个问题...列表的许多操作可能会使存储的引用无效,因为 std::list 仅保证元素的顺序类型为T。如果您想在多个位置存储对这些元素的引用,请使用 std::tr1::shared_ptrstd::list; >。然后,您可以安全地删除或添加(甚至重新定位)列表中的元素,并且保留在其他位置的引用仍然有效。请注意存储 std::listiterators,问题是一样的。

Something smells fishy here... You are storing object of type T in a std::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, since std::list<T> only guarantees a sequential order of values of elements of type T. If you want to store references to those elements in several places use std::tr1::shared_ptr<T> and std::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 storing std::list<T>iterators, the problem would be the same.

情话已封尘 2024-09-24 22:03:24

我指的是你的回复。抱歉,我没搞清楚账号...
请考虑以下几点:

std::list<A> tList;
A tA;

tList.push_back(tA);
assert(&tA == &tList.back()); // boom!

A *tAPtr = &tList.front();

tList.erase(tList.front());
// try to access tAPtr:
tAPtr->Foo(); // boom! (probably)

要点是 A 的实例是按值存储的(=复制的),因此您所做的事情本质上是不安全的。使用 std::list; > 相反!

I am referring to your response. Sorry, I didn't get the account thing right...
Please consider the following:

std::list<A> tList;
A tA;

tList.push_back(tA);
assert(&tA == &tList.back()); // boom!

A *tAPtr = &tList.front();

tList.erase(tList.front());
// try to access tAPtr:
tAPtr->Foo(); // boom! (probably)

The point is that instances of A are stored by value (= copied), so what you are doing is inherently unsafe. Use std::list<std::tr1::shared_ptr<A> > instead!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文