我在C ++程序中有一个std :: list,它包含A类的对象。 可以说我有10个物体。我有一个存储的第6个对象的引用,在另一个数据结构中说ref_6。假设我需要从列表中删除第8个元素。为此,我将使用pop_front 8次并在向量中存储8个对象,并使用push_front 7次将前7个元素插入列表中,所以现在我的结果列表将有9个元素。现在,当我尝试访问存储在ref_6中的对象时,这是第6个元素,我无法做到。这个引用中有一些垃圾值。 我假设当我进行弹出和推送时,同一对象的内存位置会发生变化。我该如何处理?
答案 0 :(得分:2)
为什么要以这种方式抹去东西? 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
没有其他迭代器失效。 (实际上,擦除元素会使对它的任何引用无效。)
*您可能甚至不应该使用列表。在学习数据结构方面,列表很不错,但它们非常糟糕。
答案 1 :(得分:0)
该列表将其元素存储在不连续的内存块中,当从列表中删除该元素时,该内存块将被释放。因此,引用(仅作为指针实现)指向已释放内存的元素。
从列表中删除给定元素的更简单方法是让迭代器指向它并使用方法
std::list::iterator = /*somehow get the iterator to the 8th element*/
yourList.erase(8th_element_iterator);
第一步(将迭代器设置为第8个元素)可以通过获取列表开始的迭代器并向前推进7个位置来完成:
std::list::iterator first_iter = yourList.begin();
std::list::iterator 8th_iter = std::advance(first_iter, 7);
答案 2 :(得分:0)
这里闻起来有些腥味......你正在按T
的值存储std::list<T>
类型的对象。您可以在其他位置保留对这些对象的引用。那是对的吗?如果是,我会看到几个问题......许多列表操作可能会使存储的引用无效,因为std::list<T>
仅保证T
类型元素的值的连续顺序。如果您想在多个地方存储对这些元素的引用,请使用std::tr1::shared_ptr<T>
和std::list<std::shared_ptr<T> >
。然后,您可以安全地删除或添加(甚至重新定位)列表中的元素,并保留在其他位置的引用保持有效。谨防存储std::list<T>iterators
,问题将是相同的。
答案 3 :(得分:0)
我指的是你的回答。对不起,我的帐号没问题... 请考虑以下事项:
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<std::tr1::shared_ptr<A> >
!