C ++容器的问题

时间:2010-09-05 07:42:26

标签: c++ list memory-management stl containers

我在C ++程序中有一个std :: list,它包含A类的对象。 可以说我有10个物体。我有一个存储的第6个对象的引用,在另一个数据结构中说ref_6。假设我需要从列表中删除第8个元素。为此,我将使用pop_front 8次并在向量中存储8个对象,并使用push_front 7次将前7个元素插入列表中,所以现在我的结果列表将有9个元素。现在,当我尝试访问存储在ref_6中的对象时,这是第6个元素,我无法做到。这个引用中有一些垃圾值。 我假设当我进行弹出和推送时,同一对象的内存位置会发生变化。我该如何处理?

4 个答案:

答案 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> >