iterator erase(iterator position); // (1) C++17
iterator erase(const_iterator position); // (2) C++11
size_type erase(const key_type& k); // (3) C++11
iterator erase(const_iterator first, const_iterator last); // (4) C++11
概要
指定された要素を削除する
要件
position
は、有効で、かつ、間接参照可能な(dereferenceable、つまりcend()
ではない)当該コンテナを指す読み取り専用イテレータでなければならない。first
とlast
は[first, last)
が当該コンテナの有効な範囲である読み取り専用イテレータでなければならない。
なお、規格書ではfirst
は間接参照可能である必要があることになっているが、他の種類のコンテナの要件と照らし合わせると、間接参照可能である必要はない(つまり、first
とlast
が共にcend()
でも良い)ものと思われる。
効果
- (1), (2) :
position
で指定された要素を削除する。 - (3) :
k
と等価なキーの要素を削除する。 - (4) : イテレータ範囲
[first, last)
にある要素を全て削除する。
戻り値
- (1), (2) : 「削除前に、削除された要素の次だった位置」を指すイテレータ。
erase()
を呼び出しても削除された要素以外を指す全てのイテレータは無効にならないため、std::next(position)
と同じ位置を指すiterator
である。
なお、position
はconst_iterator
なのに対して、戻り値はiterator
であるため注意が必要だが、非順序連想コンテナの場合いずれにせよどちらも読み取り専用イテレータである。 - (3) : 削除した要素数。
- (4) : 「削除前に、削除された要素の範囲の次だった位置」を指すイテレータ。
erase()
を呼び出しても削除された要素以外を指す全てのイテレータは無効にならないため、last
と同じ位置を指すiterator
である。
なお、first
及びlast
はconst_iterator
なのに対して、戻り値はiterator
であるため注意が必要だが、非順序連想コンテナの場合いずれにせよどちらも読み取り専用イテレータである。
また、要件に示したようにfirst
が間接参照可能である必要がなかった場合にも、他の種類のコンテナの戻り値と照らし合わせると、last
と同じ位置を指すiterator
を返すのが適切であるものと思われる。
例外
- (1), (2) : 投げない。
- (3) : コンテナの
key_equal
とhasher
のオブジェクト(それぞれkey_eq()
とhash_function()
が返すオブジェクト)が例外を投げなければ、例外を投げない。 - (4) : 投げない。
計算量
- (1), (2) : 平均的なケースでは定数(O(
1
))だが、最悪のケースではコンテナの要素数に比例(O(size()
)) - (3) : 平均的なケースでは削除された要素数に比例(O(
count(k)
))だが、最悪のケースではコンテナの要素数に比例(O(size()
)) - (4) : 平均的なケースでは指定された範囲の要素数に比例(O(
std::distance(first, last)
))だが、最悪のケースではコンテナの要素数に比例(O(size()
))
備考
削除された要素を指すイテレータ、および、参照のみ無効になる。なお、規格書に明確な記載は無いが、削除された要素を指すポインタも無効になる。
例
基本的な使い方 (C++11)
#include <iostream>
#include <unordered_set>
#include <iterator>
#include <algorithm>
template <class C>
void print(const char* label, const C& c, std::ostream& os = std::cout)
{
os << label << " : ";
std::copy(c.cbegin(), c.cend(), std::ostream_iterator<typename C::value_type>(os, " "));
os << '\n';
}
int main()
{
// 指定した位置にある要素を削除((1)の形式)
{
std::unordered_multiset<int> ums{ 1, 3, 5, 7, 9, 3, };
print("(1) erase(const_iterator) before", ums);
auto it1 = std::next(ums.cbegin(), 3);
std::cout << "argument: " << *it1 << '\n';
auto it2 = ums.erase(it1);
std::cout << "return value: " << *it2 << '\n';
print("after", ums);
std::cout << std::endl;
}
// 指定したキーと等価な要素を削除((3)の形式)
{
std::unordered_multiset<int> ums{ 1, 3, 5, 7, 9, 3, };
print("(3) erase(const value_type&) before", ums);
auto count1 = ums.erase(5);
auto count2 = ums.erase(8);
auto count3 = ums.erase(3);
std::cout << "argument: 5, 8, 3" << '\n';
std::cout << "return value: " << count1 << ", " << count2 << ", " << count3 << std::endl;
print("after", ums);
std::cout << std::endl;
}
// 指定した位置にある要素を削除((4)の形式)
{
std::unordered_multiset<int> ums{ 1, 3, 5, 7, 9, 3, };
print("(4) erase(const_iterator, const_iterator) before", ums);
auto it1 = std::next(ums.cbegin());
auto it2 = std::next(it1, 2);
std::cout << "arguments: " << *it1 << ", " << *it2 << '\n';
auto it3 = ums.erase(it1, it2);
std::cout << "return value: " << *it3 << '\n';
print("after", ums);
std::cout << std::endl;
}
}
57
std::cout << "return value: " << count1 << ", " << count2 << ", " << count3 << std::endl;
#include <iostream>
#include <unordered_set>
#include <iterator>
#include <algorithm>
template <class C>
void print(const char* label, const C& c, std::ostream& os = std::cout)
{
os << label << " : ";
std::copy(c.cbegin(), c.cend(), std::ostream_iterator<typename C::value_type>(os, " "));
os << '\n';
}
int main()
{
// 指定した位置にある要素を削除((1)の形式)
{
std::unordered_multiset<int> ums{ 1, 3, 5, 7, 9, 3, };
出力例
(1) erase(const_iterator) before : 9 7 5 1 3 3
argument: 1
return value: 3
after : 9 7 5 3 3
(3) erase(const value_type&) before : 9 7 5 1 3 3
argument: 5, 8, 3
return value: 1, 0, 2
after : 9 7 1
(4) erase(const_iterator, const_iterator) before : 9 7 5 1 3 3
arguments: 7, 1
return value: 1
after : 9 1 3 3
注:unordered_multiset
は非順序連想コンテナであるため、出力順序は無意味であることに注意
イテレート中に要素を削除する (C++11)
#include <iostream>
#include <unordered_set>
int main()
{
std::unordered_multiset<int> ums = {3, 1, 4};
// イテレート中に要素削除をするような場合には、
// 範囲for文は使用できない
for (auto it = ums.begin(); it != ums.end();) {
// 条件一致した要素を削除する
if (*it == 1) {
// 削除された要素の次を指すイテレータが返される
it = ums.erase(it);
}
// 要素削除をしない場合に、イテレータを進める
else {
++it;
}
}
for (const auto& x : ums) {
std::cout << x << std::endl;
}
}
xxxxxxxxxx
#include <iostream>
#include <unordered_set>
int main()
{
std::unordered_multiset<int> ums = {3, 1, 4};
// イテレート中に要素削除をするような場合には、
// 範囲for文は使用できない
for (auto it = ums.begin(); it != ums.end();) {
// 条件一致した要素を削除する
if (*it == 1) {
// 削除された要素の次を指すイテレータが返される
it = ums.erase(it);
}
// 要素削除をしない場合に、イテレータを進める
else {
++it;
出力例
4
3
バージョン
言語
- C++11
処理系
- Clang: 3.1 ✅
- GCC: 4.7.0 ✅
- ICC: ?
- Visual C++: ?
関連項目
名前 | 説明 |
---|---|
emplace |
コンテナ内への要素の直接構築 |
emplace_hint |
挿入位置のヒントを使用したコンテナ内への要素の直接構築 |
insert |
要素の追加 |
clear |
全要素の削除 |
swap |
内容の交換 |
参照
- LWG Issue 518. Are
insert
anderase
stable forunordered_multiset
andunordered_multimap
?- 安定性の保証が規定された経緯のレポート
- LWG Issue 2059. C++0x ambiguity problem with
map::erase
- C++17で、
erase(iterator)
を追加
- C++17で、