C++のSTL(標準テンプレートライブラリ)でwhileループ中にmapのメンバーを削除する方法を調べてみました。
目次
C++のSTL(標準テンプレートライブラリ)
Javaのプログラムを数年やってきた後で、C++を使い始めるとC++の標準テンプレートライブラリ(Standard Template Library)のコンテナに病み付きになります。
これなくして、C++のプログラマーはやってこれたのでしょうか。
vector, list, set, map, multiset, multimapなど基本はJavaで標準実装されているものと似ています。というかほとんど一緒です。
whileループ中にmapのメンバーを削除する方法
ところで、mapにデータを格納して、whileループで読みだす時に格納されたデータを削除したいことがよくあります。
削除する方法・コードのサンプルは以下の通りです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#include "stdafx.h" #include <iostream> #include <map> #include <utility> using namespace std; int _tmain(int argc, _TCHAR* argv[]) { map<int, bool> map1; map<int, bool>::iterator it; map1.insert(make_pair(1, true)); map1.insert(make_pair(2, false)); map1.insert(make_pair(3, true)); map1.insert(make_pair(4, false)); it = map1.begin(); while (it != map1.end()) { if (it->second == true) { // map1.erase(++it); // NGコード map1.erase(it++); // OKコード } else { ++it; } } for(it = map1.begin(); it != map1.end();it++) { cout << "map has " << it->first <<endl; } return 0; } |
上記のプログラムを実行すると以下の結果になります。
1 2 |
map has 2 map has 4 |
ポイントはイテレータをインクリメントしてから元の方を削除しているところです。
このように削除しないと動作しません。
map1.erase(++it)はNG
map1.erase(it++)はOK
です。
Expression: map/set erase iterator outside range
NGコードの方を実行すると以下のエラーが発生します。
Debug Assertion Failed!
Program: C:\Windows\system32\MSVCP110D.dll
File: C:\Program Files (x86)\Microsoft Visual Studio
11.0\VC\include\xtree
Line: 1326Expression: map/set erase iterator outside range
For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.
まとめ
コンテナのループで一部のメンバーを削除するケースはよくあります。
forループで同様のことが出来ればよいのですが、ちょっと難しそうです。
メンバ削除の場合はforループでなくてwhileループを使いましょう。
プログラミングの無料レッスン体験
約8,000名の受講生と80社以上の導入実績のあるプログラミングやWebデザインのオンラインマンツーマンレッスンCodecamp
<Codecampの特徴>
1 現役エンジニアによる指導
2オンラインでのマンツーマン形式の講義
3大手企業にも導入されている実践的なカリキュラム
↓無料体験レッスン実施中です。
コメント
[…] C++のSTL(標準テンプレートライブラリ)でwhileループ中にmapのメンバーを削除… […]