2011-07-30 41 views
7

如果只有指向要刪除的元素的迭代器,是否可以從std::list中刪除元素?我有大量的函數需要迭代器來列出元素,並且將自己的list傳遞給它們中的每一個都是非常不方便的。從列表中刪除元素只有迭代器

+1

請注意,以這種方式使用迭代器不利於將其用作設計模式,但這並不是說在許多情況下它不是正確的做法(例如通過查看一組元素)。 – Jeremy

+0

http:// stackoverflow.com/questions/596162/can-you-remove-elements-from-a-stdlist-while-iterating-through-it – nielsj

+0

@Jeremy:實際上,它不再是使用迭代器作爲設計模式。但是,它在迭代器失效方面的語義很差。在許多容器中,刪除一個項目會使所有迭代器失效,包括當前用於迭代元素的迭代器。 –

回答

3

編輯:

你不能使用單個迭代器。

如果您有開始/結束迭代器,則可以使用std::remove算法將要擦除的所有元素移到最後,並在稍後刪除它們。

如果你不這樣做,或者上述方法對你目前的設計是不可行的,我建議改變你的功能,採取std::pair<std::list<T>, std::list<T>::iterator>或類似的東西。

+2

但它也需要列表。 – Dani

+1

std :: remove()函數不會從容器中刪除項目,因爲它不能。查看[erase-remove idiom](http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Erase-Remove)。 –

+0

@André - 這就是我所說的。使用它將它們移動到最後_並在稍後刪除它們_ – Node

0

不,這是不可能的。顧名思義,迭代器的工作就是迭代序列的元素。查看SGI page on iterators,獲取C++標準庫中迭代器設計的摘要。

+0

因爲'list'是一個雙向鏈表,所以你可不寫一個函數來操作'next'和'previous'指針,這樣它就會刪除這個元素?或者這真的很糟糕?還是僅僅是這些成員是私人的? –

+0

@Seth:是的,這在技術上是可行的。例如,在Java中,迭代器具有[remove method](http://download.oracle.com/javase/1.4.2/docs/api/java/util/Iterator.html#remove())。但是,這不是C++迭代器設計的一部分。我想標準委員會更喜歡與其他容器的一致性。 –

+0

@Seth:這可以針對特定供應商庫的特定版本完成。但是,這意味着很多非標準(並且絕對不可移植)的代碼。此外,成員可能是私人的。 –

3

不,你不能。迭代器是指針之後建模的輕量級對象,並且不會引用它們引用的容器。 (儘管一些實現在調試模式下是內部執行的)。

就像你不能從數組中「移除」一個對象,當你擁有一個指向數組的指針時,你不能從容器中移除一個對象,訪問容器。

-1

您可以手動執行此操作。迭代器將_M_node作爲當前節點公開。你可以這樣做:

itr._M_node->_M_prev->_M_next = itr._M_node._M_next; 
+2

這只是特定迭代器到具體實現的特定版本的特定容器中的情況,它是一個實現細節,甚至可以通過使用正確的預處理器標記關閉。此外,它可能會弄亂容器的內部,你需要知道爲什麼。 – sbi

+0

我沒有說它的乾淨。你的警告是正確的。 – Dani

+1

更不用說你沒有更新'_M_next'的'_M_prev'指針(因爲它是一個閃爍的列表)。這是我想到的,但是這段代碼也需要使用不同的版本/編譯器。 –

1

雖然其他人提到你不能這樣做,我想我可以提供爲什麼。

我相信具體的技術原因(而不是設計理由)是列表做了一些維護,例如跟蹤大小,例如需要某些動作必須通過它們才能進行維護。

正是因爲這個原因,可能會提供的任何破解可能會失敗。

+0

這是一個很好的想法,儘管看起來你可以讓迭代器告訴他們的父列表他們正在刪除自己或某物。 –