2010-09-05 47 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> >