
コンテナの内容を変えた後に内容を変える前のiteratorを使用することはできないと聞きました。ので、連続して何らかのコンテナ内のデータを変更しつつ、探索する場合にも、iteratorは最初から探索を始めないといけないと思っています。
例えば以下のように
#include <stdio.h>
#include <list>
struct data
{
int value;
data(int value)
{this->value = value;}
};
typedef std::list<data> DataList;
typedef std::list<data>::iterator DataIterator;
bool EraseValue(DataList*dataList, int value)
{
DataIterator iterator= dataList->begin();
while(iterator != dataList->end())
{
if(iterator->value == value)
{
dataList->erase(iterator);
return true;
}
iterator++;
}
return false;
}
int main()
{
//データを入れる
DataList dataList;
for(int i=0;i<10; i++)
dataList.push_back(data(i));
//指定のデータを探し、消す
int Value[] = {4,5,7};
EraseValue(&dataList, Value[0]);
EraseValue(&dataList, Value[1]);
EraseValue(&dataList, Value[2]);
//結果表示
DataIterator iterator = dataList.begin();
while(iterator != dataList.end())
{
printf("%d\n",iterator->value);
iterator++;
}
return 0;
}
ここで、新しい値の探索を始めるたびに、最初から探索をはじめる部分が無駄であると思っています。探索するデータは、上の例のように、必ず前回探したものの後にあることはわかっているとして、これより効率のよい方法はないでしょうか?自分の中での理想は、削除したiteratorの直前に使った(削除されていない)iteratorの位置から探索を始めるのがいい思っているのですが、これはどうやらできないこと(やってはいけないこと?)の様です。
コンテナをstd::listに限定した場合でも構いません。
ご教授よろしくお願いします。
No.2ベストアンサー
- 回答日時:
ここに要素の削除によるイテレーターの無効化について情報が乗っています。
std::listに限って言えば要素が削除された場合、無効になるイテレーターは削除対象の要素を示していたイテレーターのみです。
> 必ず前回探したものの後にあることはわかっている
場合ならば以下のようにしても良いと思います。
bool EraseValue(DataList*dataList, int* value, size_t erasenum)
{
DataIterator iterator= dataList->begin();
while(iterator != dataList->end() && erasenum > 0)
{
if(iterator->value == value)
{
DataIterator tmp = iterator; // 削除対象を見つけたのでイテレーターを保存
++iterator; // 次のイテレーターに移動
dataList->erase(tmp); // 削除。この時点でtmpは無効だが、iteratorは利用可能
++value; // 次の削除対象に移す
--erasenum; // 削除数を減らす
}
else
{
iterator++;
}
}
return false;
}
迅速な返答ありがとうございます。
疑問が完全に氷解しました。ありがとうございます。
自分の環境では、直前のものを使うのに成功していたのですが、"たまたま"かどうか裏が取れなかったので、使用していませんでした。
No.1
- 回答日時:
コンテナから任意の要素を消したいという話なら、
remove_ifを使えばいいと思うのですが何か問題があるのでしょうか?
STL Algorithm詳解 - 置き換え、削除
http://www.wakhok.ac.jp/~sumi/stl/manual/remove. …
返答ありがとうございます。
当方、まだまだ未熟で、STLのalgorithmなどは、一度も使ったことがありません。こんな便利なことができるのですね。
是非試してみます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- Java どんな時にIteratorを使うと便利なのですか 2 2022/12/07 05:30
- C言語・C++・C# C言語プログラム変更 2 2022/12/21 15:03
- Visual Basic(VBA) Excelで下記のようにマクロを作ったところ、一回目は実行できたのですが、二回目以降「実行時エラー1 1 2022/03/25 08:08
- Java どうしてListオブジェクトをIteratorに変換するのですか 1 2022/12/03 17:45
- Visual Basic(VBA) 列と行の名前(重複あり)が交差するセルに、データを入力したい 2 2022/06/25 22:42
- Visual Basic(VBA) VBAのユーザーフォームのテキストボックスに入力制限をしたい 6 2022/11/15 08:28
- Visual Basic(VBA) VBAで日付入力しているのですが 4 2023/03/02 11:25
- C言語・C++・C# c言語の問題です 課題1 (二分探索木とセット) 大きさ size の配列 array を考える。す 2 2023/01/10 21:08
- Visual Basic(VBA) 検索のユーザーフォームの表示について 1 2023/03/27 23:31
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
メモリをアドレスを直接指定し...
-
JSONで文字列が長い時
-
map(STL)でinsertを行いたいで...
-
CGI(Perl)で、Net::FTPを使いたい
-
Application.ScreenUpdating = ...
-
実行時エラー 3020の対策
-
文字の横にプルダウンを表示さ...
-
16進の10進変換について
-
formで特定のinputを送信しない...
-
セレクトメニューで2つの項目...
-
複数列を持ったリストボックス...
-
C言語のflagの使い方が分かりま...
-
switch文のエラーについて
-
実行中の変数の中身をイミディ...
-
<SELECT>タグの折り返し
-
optionのselectedは更新時は効...
-
シェルスクリプトで、空白(ス...
-
フォームの「キャンセル」ボタ...
-
pythonを使ったプログラミング...
-
VBAでPDFのコピーとリネームを...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
JSONで文字列が長い時
-
メモリをアドレスを直接指定し...
-
複数行URLエンコードができるCG...
-
CGIでの表示の不具合について。
-
前のページへ戻ったときのプル...
-
Perlでアルファベットを数...
-
map(STL)でinsertを行いたいで...
-
途中まで出来ているのですが‥(D...
-
半角スペースが有効にならない。
-
CGIやPHPで外部ファイルの内容...
-
linq で 楽天ウェブサービスのX...
-
CGIからメールに書き出しする際...
-
iteratorの再利用について
-
Excel VBAで行追加後の...
-
ホームページ上にある表に書き...
-
CGIでのページ指定~その(2)
-
リロード後にプルダウンの選択...
-
連結リストについて
-
VB2010 のユーザコントロールの...
-
【C#】数値の範囲チェックについて
おすすめ情報