概要
簡単な様で意外と難しいc++でのループ内のvector要素の削除。
とりあえず答えが知りたい方は一番下に行ってください笑
c++において、ループ内でvectorから要素を削除する場合、最初に思い浮かぶ形
基本方針は以下です。
// 0 〜 4が入ったvector型変数numbersを用意
std::vector<int> numbers {0, 1, 2, 3, 4};
// aとbを除きたい
int a = 1;
int b = 3;
// iteratorで内部要素を回し、該当値であればその要素を削除
for (auto itr = numbers.begin(); itr != numbers.end(); itr++)
{
if (((*itr) == a) || ((*itr) == b))
{
numbers.erase(itr);
}
}
まず、やりたい事を順当にコード化するとこんな感じです。
が、ある程度コーディングをしている人はこれが危ない事にはすぐに気付きます。
eraseをした時点で内部要素が全て前にずれて来ますので、実行時にクラッシュすると。
そして、これを解決した事のある人は、以下の解決方法をまず思い浮かべるのではないでしょうか。
そうか、最後の要素から逆に走査、比較、削除を行えば良いんだと。
例えば、iOSではNSArrayのインスタンスに対して、reverseObjectEnumeratorなるメソッドを投げるとそんなのが返って来たな、cocosでも出来ないかな、なんて考えます。
これが、あるんですよね。
http://www.cplusplus.com/reference/vector/vector/rbegin/
http://www.cplusplus.com/reference/vector/vector/rend/
こいつがreverse_iteratorを返してくれてitr++するとvector要素を逆に走査してくれます。
そんなこんなで以下のコードを書きます。
for (auto itr = numbers.rbegin(); itr != numbers.rend(); itr++)
{
if(((*itr) == a) || ((*itr) == b))
{
numbers.erase(itr);
}
}
これで、安全に要素が消せる…!
ところがしかし、eraseの引数はiterator型でないと駄目だとコンパイラに怒られる始末。。。
おい、一体どうすれば良いんだよと途方に暮れ、ようやく出来たのが以下のコード。
c++のループ内でvectorから安全に要素を削除する方法はこれだ!
auto itr = numbers.begin();
while (itr != numbers.end())
{
if(((*itr) == a) || ((*itr) == b))
{
itr = numbers.erase(itr);
}
else
{
itr++;
}
}
ポイントは、numbers.erase(itr)の返り値をitrに代入する事。
erase(itr)は要素を削除し、その次の要素を返してくれるそうです。
【cocos2d-x】cocos記事一覧
cocos記事一覧 Pimpl 激震が走った、Pimplイディオム enum enum struct(class)とは cast 決定版!*_castまとめ sqlit...
Twitterフォローお願いします
「次回以降も記事を読んでみたい!」「この辺分からなかったから質問したい!」
そんな時は、是非Twitter (@daiki1003)やInstagram (@ashdik_flutter)のフォローお願いします♪
Twitterコミュニティ参加お願いします
Twitterコミュニティ「Flutter lovers」を開設しました!参加お待ちしております😁
☕️ Buy me a coffee
また、記事がとても役に立ったと思う人はコーヒーを奢っていただけると非常に嬉しいです!
コメント