非void STL消去と同等の安全なものは何ですか?
質問
hash_mapと次のようなコードがあるとします
// i is an iterator
i = hash_map.erase(i)
しかし、GCCのSTLは消去時にイテレータを返しませんが、無効を返します。今のようなコードです
hash_map.erase(i++)
safe(つまり、イテレータを無効にしないか、他の予期しないまたは不快なことを行いませんか?)これはhash_mapであることに注意してください。
解決
はい、これは安全です。現在の値が消去される前に、 i
の値が次の値に設定されるためです。
ハッシュコンテナに関するSGIドキュメントによると、 -消去された要素、またはサイズ変更についても(挿入によってサイズ変更が行われるかどうかについての言葉はありません。そのため、可能性として認めるように注意してください)ただし、これは、トラバーサルなどでコンテナのサイズを変更するために邪魔にならない限り、ここでは当てはまりません。 :-)
他のヒント
消去をカプセル化して、使用するすべてのコンテナに同じインターフェイスを提供できます:
namespace detail {
template<typename Container, typename R>
struct SelectErase {
// by default, assume the next iterator is returned
template<typename Iterator>
Iterator erase(Container& c, Iterator where) {
return c.erase(where);
}
};
// specialize on return type void
template<typename Container>
struct SelectErase<Container, void> {
template<typename Iterator>
Iterator erase(Container& c, Iterator where) {
Iterator next (where);
++next;
c.erase(where);
return next;
}
};
template<typename I, typename Container, typename R>
SelectErase<Container,R> select_erase(R (Container::*)(I)) {
return SelectErase<Container,R>();
}
} // namespace detail
template<typename Container, typename Iterator>
Iterator erase(Container& container, Iterator where) {
return detail::select_erase<Iterator>(&Container::erase).erase(container, where);
}
これには次のいずれかが必要です。
- c.eraseは、次のアイテムの反復子を返します。これがベクター、デキュー、リストの仕組みです。
- c.eraseはvoidを返し、次の反復子を無効にしません。これが、map、set、および(非stdlib)hash_mapの仕組みです。
パレードで雨が降るのは嫌いですが、あなたが提案することは安全だとは思いません。
i ++はポストインクリメント演算子です。つまり、消去の呼び出し後にiがインクリメントされます。ただし、eraseは、消去される要素を指すすべての反復子を無効にします。したがって、iがインクリメントされるまでに、それはもう有効ではありません。
運がよければ、ある日までは偶然に正しく動作するかもしれません。
私が知る限り、これを回避する方法はありませんが、次のようなものです:
// tmp and i are both iterators
tmp = i;
++i;
hash_map.erase(tmp);
所属していません StackOverflow