2010-09-05 23 views
1

我在C++程序中有一个std :: list,其中包含A类的对象。012.g可以说我有10个对象。我有一个参考存储在第六个对象,在另一个数据结构说ref_6。假设我需要从列表中删除第8个元素。为此,我将使用pop_front 8次并将8个对象存储在一个向量中,并使用push_front 7次将前7个元素重新插入列表中,以便现在我的结果列表中将包含9个元素。现在,当我尝试访问存储在第6个元素ref_6中的对象时,我无法做到这一点。这个参考中有一些垃圾值。 我假设当我做一个弹出和推,同一对象的内存位置改变。我如何处理这个问题?C++容器的问题

回答

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 

而且没有其他迭代器失效。 *你可能甚至不应该使用列表(事实上,擦除元素无效给它的任何引用。)


。列表在学习数据结构方面很不错,但它们非常糟糕。

+0

所以这样,列表大小(内存开始和内存结束位置)保持不变,只是其中一个元素被删除/无效。不是吗? – cyrux 2010-09-05 08:08:40

+1

我很好奇你对现实生活中的列表使用情况的评论----正如你所说,它出现在STL中:在常量时间内插入或删除任何元素 – 2010-09-05 08:13:35

+1

@cyrux:是的,链接列表将删除该元素只有其他人是有效的。 @Dbger:标准库包含它,因为它是如此普通的数据结构,并且因为它有它的用途。但这些用途很少;你的主要操作将基本上遍历容器并经常移除元素,并且频繁地执行*。可怕的缓存一致性和线性访问时间使得它在实践中非常缓慢;即使你经常从中间抹掉某些东西,由于局部性,“vector”/“deque”也会更好。 – GManNickG 2010-09-05 08:16:42

0

该列表将其元素存储在不连续的内存块中,当元素从列表中删除时,它将被释放。所以引用(它只是作为一个指针来实现)指向一个内存已经被释放的元素。

更容易从列表中删除一个给定的元素的方法是让迭代器,指向它和使用方法

std::list::iterator = /*somehow get the iterator to the 8th element*/
yourList.erase(8th_element_iterator);

第一步(让迭代器到8元),可以完成例如通过获取列表的begininning的迭代器和推进其7位前锋:

std::list::iterator first_iter = yourList.begin();
std::list::iterator 8th_iter = std::advance(first_iter, 7);

0

东西味道腥这里...你是存储Ø价值为std::list<T>T类型的对象。您保持对其他地方的这些对象的引用。那是对的吗?如果是的话,我会看到几个问题......许多列表操作可能会使存储的引用无效,因为std::list<T>仅保证类型为T的元素的的连续顺序。如果您想在几个地方存储对这些元素的引用,请使用std::tr1::shared_ptr<T>std::list<std::shared_ptr<T> >。然后,您可以安全地删除或添加(甚至重新定位)列表中的元素,并保留在其他地方的引用仍然有效。当心存储std::list<T>iterators,问题会是一样的。

+0

你说我按值保存类型为T的对象,但在stl_list中,push_front具有此原型void push_front(const value_type&__x)。所以这不是持有的参考,这是价值。另外,在其他地方,当我说我举行参考,我实际上是使用指针,我相信是造成这个问题。所以你说,如果我使用shared_ptr列表,那么我可以删除和添加元素,并且我对这些元素的引用可以正常工作。如果我更改列表中元素的排序,如使用pop_front来获取元素,然后push_back,这是否适用? – cyrux 2010-09-05 13:15:31

+0

在这种情况下,我的shared_ptr会正常工作吗? – cyrux 2010-09-05 13:18:13

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