假設在C++ 11程序的主線程中,我構建了一個std::set
,填充項並從中提取一個迭代器it
。之後,從另一個線程開始修改集合,使得元素只能添加到它但不能擦除。迭代器的有效性和線程
it
在集合被修改時是否有效,或者當該集合正在被其他線程的插入操作修改時,是否應該認爲it
無效?
假設在C++ 11程序的主線程中,我構建了一個std::set
,填充項並從中提取一個迭代器it
。之後,從另一個線程開始修改集合,使得元素只能添加到它但不能擦除。迭代器的有效性和線程
it
在集合被修改時是否有效,或者當該集合正在被其他線程的插入操作修改時,是否應該認爲it
無效?
從部分23.2.1 [container.requirements.general]
:
除非另有規定(顯式或通過在其它功能方面定義一個函數),調用一個容器成員函數或傳遞容器作爲參數傳遞給一個庫函數不應該使迭代器失效或更改該容器內的對象的值。
對於關聯容器如std::set
,部分23.2.4([associative.reqmts]
)表示:
的
insert
和emplace
成員不應一個FF ECT迭代器和引用到容器的有效性,並且erase
構件應僅使迭代器和對擦除元素的引用無效。
所以你的迭代器在插入其他項後仍然有效。
但是,線程安全是完全不同的話題。
第17.6.5.9([res.on.data.races]
)規定
操作上通過調用一個標準庫的容器或字符串成員函數可以訪問底層的容器獲得的迭代器,但不應修改它。
由於在讀取容器它被更新,而結果,它不一定是安全的,同時插入收集從另一個線程使用std::set
迭代器。您的實施可能會提供更有力的保證。
這是在單線程模型下。如果執行諸如「i ++」的併發操作,中間狀態仍然可能導致無效的迭代器。 – spraff
也許我在這裏拆分頭髮,但是這些保證包括迭代器在容器成員函數的調用的_any_點處不失效嗎?也就是說,什麼阻止實現在調用insert()期間使迭代器無效並在退出該方法之前重新驗證它? – bluescarni
@bluescarni:如前所述,線程安全是一個單獨的主題。我已經添加了我認爲是控制要求的內容。 –
好:[迭代器無效](http://stackoverflow.com/questions/6438086/iterator-invalidation-rules) –
@Als:但這並沒有解決線程問題。 –
@ BenVoigt:是的,因此我將它添加爲好讀,而不是重複:) –