質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

4回答

5288閲覧

c++におけるイテレータの使い方

torimingo

総合スコア122

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2019/02/24 11:39

編集2019/02/24 12:48

C++で、イテレータの使い方がよくわかりません。
以下のコードのmain()でコメントアウトした箇所をaiueo()で処理したいです。
コンパイルは通りますが、実行時エラー(Segmentation fault (コアダンプ))で落ちます。

c++

1 1 #include <iostream> 2 2 #include <vector> 3 3 #include <string> 4 4 5 5 using namespace std; 6 6 7 7 void aiueo(vector<string> *v, vector<string>::iterator itr, double tmp){ 8 8 itr = v->insert(itr - 1, to_string(tmp)); 9 9 itr = v->erase(itr + 1); 10 10 itr = v->erase(itr); 11 11 itr = v->erase(itr); 12 12 itr--; 13 13 } 14 14 15 15 int main(){ 16 16 double tmp; 17 17 18 18 vector<string> v {"2", "+", "3"}; 19 19 20 20 for(vector<string>::iterator itr = v.begin(); itr != v.end(); ++itr) { 21 21 if(*itr == "+"){ 22 22 tmp = stod(*(itr - 1)) + stod(*(itr + 1)); 23 23 24 24 //itr = v.insert(itr - 1, to_string(tmp)); 25 25 //itr = v.erase(itr + 1); 26 26 //itr = v.erase(itr); 27 27 //itr = v.erase(itr); 28 28 //itr--; 29 29 30 30 aiueo(&v, itr, tmp); 31 31 } 32 32 } 33 33 34 34 cout << v[0] << endl; 35 35 return 0; 36 36 }

どのようにしたら、いいのでしょうか。
aiueo()を使わないで、main()でコメントアウトしている箇所の処理を使うと、正常な結果として、5が出力されます。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nskydiving

2019/02/24 11:52

「vector<string>::iterator」が「vector<string>::iteror」になっているので、コンパイルエラーになるかと思いますが、本当に提示されたコードであっていますか? > コンパイルは通りますが、実行時エラー(コアダンプ)で落ちます。 そのエラーメッセージも提示してください。
yumetodo

2019/02/24 11:57

そもそも論としてコンテナとイテレータ両方渡すというのは何がしたいのかわからないというか、どっちかでいいのではという思いが
torimingo

2019/02/24 12:51 編集

>>nskydivingさん コードを全体的に修正しました。 エラーメッセージは「Segmentation fault (コアダンプ)」でございます。 >>yumetodoさん 一般的には、コンテナとイテレータの両方を渡さないものなのでしょうか、慣れていないもので、すみません!
guest

回答4

0

こんにちは。

質問自体は解決していますが、1つ危険な処理があるので補足です。

std::vectorの内部実装はrealloc的な動作をします。
イテレータはそのreallocで獲得されたメモリに割り当てられた要素へのポインタ的な動作をします。

std::vectorへinsertした時にメモリ領域が不足した場合、realloc的な動作でメモリの再獲得が行われます。この時点でイテレータが指していたメモリは一旦開放され、イテレータは不正なもの(ダングリング・ポインタ)になります。

そのような処理の場合は、std::list等を使った方が書きやすいです。std::lsitの場合も似た問題が発生しないわけではないので注意は必要ですが。

投稿2019/02/24 14:31

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

torimingo

2019/02/24 15:06

補足説明をありがとうございます。 ダングリング・ポインタという用語を初めて聞きました。 std::vectorへinsertする際には、気にしながら実装することに致します。 std::listを使用することを検討してみようと思います。
yumetodo

2019/02/25 01:18

いや、この場合は挿入位置をイテレータで持つんじゃなくて要素番号で管理すればいいかと思います。というかやっぱりイテレータを使う必要がないですね。
guest

0

ベストアンサー

aiueo 関数の引数 vector<string>::iterator itr を参照渡し(&)に変更しました。

C++

1#include <iostream> 2#include <vector> 3#include <string> 4 5using namespace std; 6 7void aiueo(vector<string> *v, vector<string>::iterator &itr, double tmp){ 8 itr = v->insert(itr - 1, to_string(tmp)); 9 itr = v->erase(itr + 1); 10 itr = v->erase(itr); 11 itr = v->erase(itr); 12 itr--; 13} 14 15int main(){ 16 double tmp; 17 18 vector<string> v {"2", "+", "3"}; 19 20 for(vector<string>::iterator itr = v.begin(); itr != v.end(); ++itr) { 21 if(*itr == "+"){ 22 tmp = stod(*(itr - 1)) + stod(*(itr + 1)); 23 24 //itr = v.insert(itr - 1, to_string(tmp)); 25 //itr = v.erase(itr + 1); 26 //itr = v.erase(itr); 27 //itr = v.erase(itr); 28 //itr--; 29 30 aiueo(&v, itr, tmp); 31 } 32 } 33 34 cout << v[0] << endl; 35 return 0; 36}

C++ の引数の渡し方はいろいろあって少し複雑なので、一度整理しておくことをおすすめします。

参考:
C++ 値渡し、ポインタ渡し、参照渡しを使い分けよう

投稿2019/02/24 13:09

nskydiving

総合スコア6500

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

torimingo

2019/02/24 13:13

ご回答をありがとうございました。 参照渡しって、こういうときに利用できるのですね。 あまり使ったことがなかったので、勉強になりました。
guest

0

問題は、引数であるitrはコピーされて関数内で使われるので
itr--しても呼び出し元では位置が動かないことですね。

void aiueo(vector<string> *v, vector<string>::iterator &itr, double tmp){

として参照を渡すか

c++

1vector<string>::iterator aiueo(vector<string> *v, vector<string>::iterator itr, double tmp){ 2 /* 省略 */ 3 return itr; 4} 5 6int main(){ 7 for(vector<string>::iterator itr = v.begin(); itr != v.end(); ++itr) { 8 itr = aiueo(&v, itr, tmp); 9 } 10}

って感じに新しいiteratorを返してやるか

投稿2019/02/24 13:02

asm

総合スコア15147

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

torimingo

2019/02/24 13:17

ご回答をありがとうございました。 itrの渡し方で苦心していました。 提示して頂いた解決方法を参考にさせて頂きます。
guest

0

何の問題もないんやが。

C++

1#include <vector> 2#include <string> 3#include <iostream> 4 5using namespace std; 6 7// itrが指す要素を"aiueo"にする 8void aiueo(vector<string>::iterator itr){ 9 *itr = "aiueo"; 10} 11 12int main(){ 13 vector<string> v { "123", "456", "789" }; 14 aiueo(v.begin()); 15 for ( auto item : v ) cout << item << ' '; 16} 17 18/* 実行結果 19aiueo 456 789 20*/

投稿2019/02/24 12:15

episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

torimingo

2019/02/24 12:53

即答して頂いてありがとうございます。 イテレータをメソッドの引数に渡す方法を提示して頂いてありがとうございます。 ・・・申し訳ないのですが、質問にあるコードを全体的に修正しました。 再度、みて頂けないでしょうか!?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問