• ベストアンサー

C++ VS2005におけるイテレーターの動作

過去にVisual Studio C++ 6.0 で作成したプロジェクトを、Visual Studio C++ 2005に変換し、ビルドしてみたところ、イテレーターに関する操作をしているところでエラーが出ました。 ---------- ソースの一部抜粋 ここから ------------- vector<char> array; // int型の動的配列 arrayに要素をpush_backする処理 while( it && it != array.end() ) // 末尾要素まで { cout << *it << endl; // *演算子で間接参照 ++it; // イテレータを1つ進める } ---------- ソースの一部抜粋 ここまで ------------- 上記のwile文のところで以下のようなエラーが発生します。 ---------- エラーメッセージ ここから ------------- error C2676: 二項演算子 '&&' : 'std::_Vector_iterator<_Ty,_Alloc>' は、この演算子または定義済の演算子に適切な型への変換の定義を行いません。(新しい動作; ヘルプを参照) 1> with 1> [ 1> _Ty=char, 1> _Alloc=std::allocator<char> 1> ] ---------- エラーメッセージ ここまで ------------- とりあえず、"while( it && it != array.end() ) "を"while( *it!=NULL && it != array.end() ) "とするとエラーはでなくなりましたが、なぜもとのように書いてはダメなのかがさっぱりわかりません。 そもそも、itと*itでは、示す内容が違っているので、これでは解決になっていないのでは、という気もします。 ヘルプを見ても、VS6.0とVS2005でvectorやiteratorの動作が変わっていることが読み取れず、困っています。 どなたかご教授ください。

  • SSMSE
  • お礼率25% (17/67)

質問者が選んだベストアンサー

  • ベストアンサー
回答No.3

> イテレータのインスタンスを作るときに > it=NULL; > としておいて、後から他のイテレータの値を代入する、 > というようなことはできないのでしょうか? iteratorはポインタではありませんから NULLの代入は合法ではありません。

SSMSE
質問者

お礼

いろいろとご教授いただき、ありがとうございました。 「iteratorはポインタみたいなもの」とイメージしていたのですが、ポインタと同じ用に扱えない部分もあるのですね。 自分でもこのあたりを再確認してみます。 長くお付き合いいただき、本当にありがとうございました。

その他の回答 (3)

  • ddnp009
  • ベストアンサー率25% (15/58)
回答No.4

iteratorはコンテナ内のどこか1要素またはendを示します。 ヒント1: end は"最後の要素"・・・ではありません。 ヒント2: コンテナが空のとき、begin() == end()になる。 ポインタのようなもの、と解釈されても結構ですが 即物的なものではなくて、概念的な(コンテナ内のどこかを指す)もの、 と解釈されたほうが良いと思いますよ

回答No.2

>> itが0/非0かを調べることに何の意味もありません。 > すみませんが、なぜ意味が無いのか、説明をいただけないでしょうか。 vectorの要素が空のとき、array.begin() == array.end() です。 なので while ( it != array.end() ) だけで十分。

SSMSE
質問者

補足

納得しました。ありがとうございました。 ちなみに、イテレータのインスタンスを作るときに it=NULL; としておいて、後から他のイテレータの値を代入する、というようなことはできないのでしょうか? 質問ばかりになってしまい、申し訳ありません・・・

回答No.1

もともとのコード: while( it && it != array.end() ) が間違ってます。 itが0/非0かを調べることに何の意味もありません。

SSMSE
質問者

補足

> itが0/非0かを調べることに何の意味もありません。 すみませんが、なぜ意味が無いのか、説明をいただけないでしょうか。 itがNULLになることは無いのでしょうか? 不勉強で申し訳ありません。

関連するQ&A

  • Vectorのポインタが入ったvector

    windows Vista sp1, Visual C++ 2008でC++の勉強をしています。 Vectorへのポインタが入ったvectorを使うプログラムを書いているのですがうまくいかず、困っています。 どういうプログラムかというと、 入力ファイルの">"という記号を区切りとして、その間にある各行をひとまとめのグループとしてvectorにいれます。 さらに各vectorのポインタをべつのvectorに入れます。 最終的に区切りの数だけvectorができ、入力ファイルを読み終わった後に すべてのvectorを"各グループのポインタが入ったvector"からループ処理ですべて出力する、というものです。 /入力ファイル input.txt/ > human cat dog > beetle dragonfly spider > salmon saury catfish > vector1には human cat dog vector2にはbeetle dragonfly spider vector3にはsalmon saury catfish が入り、 別のvectorにそれぞれのvectorのポインタをいれ、 最後にこのvectorをつかって全ファイル内容を出力するというものです。 具体的に書くと、 ">"の区切りごとの各行のstringを入れるvectorとしてeach_vector。 each_vectorのポインタを入れるvectorをvector_of_ptr_each_vectorとします。 ">"を認識するごとに new で each_vectorの領域を確保し、そのポインタをvector_of_ptr_each_vectorに追加していき、">"のない行のstringを each_vectorに入れます。 ファイルの読み込みが終わった後でvector_of_ptr_each_vectorからイテレータを使って各vector(each_vector)の全要素をそれぞれ出力する、というものです。 以下のようにコードを書きました。 #include <fstream> #include <string> #include <vector> #include <iostream> using namespace std; int main( ) { ifstream ifs("input.txt"); string buf; std::vector<string> each_vector; std::vector<std::vector<string> *> vector_of_ptr_each_vector; while(ifs && getline(ifs, buf)) { if(buf[0] == '>'){ std::vector<string>* ptr_eachvector ; ptr_eachvector = new std::vector<string>; each_vector = *ptr_eachvector ; vector_of_ptr_each_vector.push_back(ptr_eachvector) ; } each_vector.push_back(buf) ; } printf("\n output from vector of ptr of vector\n"); std::vector<std::vector<string> *>::iterator it_b = vector_of_ptr_each_vector.begin(); while( it_b != vector_of_ptr_each_vector.end() ) { std::vector<string>::iterator it_c = it_b->begin();    //エラー1 while( it_c != it_b->end() ) //エラー2 { cout << *it_c << endl; ++it_c; } ++it_b; } return 0; } ですが、エラーでビルドされず、 std::vector<string>::iterator it_c = it_b->begin(); の行に関して error C2839: invalid return type 'std::vector<_Ty> **' for overloaded 'operator ->' error C2039: 'begin' : is not a member of 'std::_Vector_iterator<_Ty,_Alloc>' while( it_c != it_b->end() )   の行に関して error C2839: invalid return type 'std::vector<_Ty> **' for overloaded 'operator ->' 1> with 1> [ 1> _Ty=std::string 1> ] error C2039: 'end' : is not a member of 'std::_Vector_iterator<_Ty,_Alloc>' 1> with 1> [ 1> _Ty=std::vector<std::string> , 1> _Alloc=std::allocator<std::vector<std::string> > 1> ] fatal error C1903: unable to recover from previous error(s); stopping compilation というようなエラーが出ます。 vectorのポインタを入れたvectorの扱い、特にイテレータに関して問題があると思うのですが原因が分かりません。 また、new でのeach_vectorの領域確保の方法も怪しいという感じがします。 解決策、アドバイスありましたらよろしくお願いします。

  • マップとアルゴリズム

    またまた質問です。 以下の処理をさせるとエラーが出ます。 どなたか見ていただけますか? 環境はWindows XP, Visual Studio.NETです。 -----処理部分------------------ map<char, int> m; for(i=0; i<10; i++){  m.insert(pair<char, int>('A'+i, i)); } reverse(m.begin(), m.end()); map<char, int>::iterator p; p = m.begin(); while( p != m.end() ){  cout << p->first << " " << p->second << endl;  p++; } ------以下エラーログ--------------- C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\utility(16) : error C2166: 左辺値は const オブジェクトに指定されています。 C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\utility(46) : コンパイルされたクラスのテンプレートのインスタンス化 'void std::swap<const _Ty1>(const _Ty &,const _Ty &)' の参照を確認してください with [ _Ty1=int, _Ty=int ] C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\utility(45): クラス テンプレートのメンバ関数 'void std::pair<_Ty1,_Ty2>::swap(std::pair<_Ty1,_Ty2>::_Myt &)' のコンパイル中 with [ _Ty1=const int, _Ty2=int ] ClusteringMain.cpp(45) : コンパイルされたクラスのテンプレートのインスタンス化 'std::pair<_Ty1,_Ty2>' の参照を確認してください with [ _Ty1=const int, _Ty2=int ] C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\utility(16) : error C2166: 左辺値は const オブジェクトに指定されています。

  • iteratorの再利用について

    コンテナの内容を変えた後に内容を変える前の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に限定した場合でも構いません。 ご教授よろしくお願いします。

  • ベクターの初歩について

    ベクターについて勉強し始めた所です。ベクターについて解らない事があるので教えて下さい。 今ベクターに10個数字を登録します。 後で3か5があれば取り除きます。 #include <vector> #include <iostream> int main(){   using namespace std;   vector<int> array1;   for( int i = 0; i < 10; ++i )     array1.push_back( i );   vector<int>::iterator it;   for(it = array1.begin(); it != array1.end(); ){     if(*it == 3 || *it==5)       it = array1.erase(it);     else       ++it;   }   for( it = array1.begin(); it != array1.end(); ++it )     cout << *it << endl;   return 0; } 一応出来たんですが、これが構造体だったらどうしたらいいのでしょう? typedef struct{   int x,y; }xy_t; vector<xy_t> array1; だとして、最初にx,yのそれぞれ10個に適当な値を入れておき、xが3か5ならそれを削除するにはどうしたらいいのでしょうか。 また、一つずつ削除する方法と、remove関数で出来そうな気がするので、もし一括で出来る方法があればそちらも2種類お願いします。 (構造体を用いたベクターの使い方が書いてある参考サイトでも結構です) XP Pro VS2005Pro よろしくお願いします。

  • C++のvectorについて教えてください。

    C++のvectorについて教えてください。 現在悩んでいる問題について簡単に説明するために、テストコードを書きました。 #include <vector> class IntType { private: int num; public: IntType( int n ):num( n ){}; }; std::vector< IntType > IntVector; void main() { } このコードをDebug版でコンパイルすると 1>c:\program files (x86)\microsoft visual studio 9.0\vc\include\xutility(285) : error C2784: 'bool std::operator <(const std::reverse_iterator<_RanIt> &,const std::reverse_iterator<_RanIt2> &)' : テンプレート 引数を 'const std::reverse_iterator<_RanIt> &' に対して 'const size_t' から減少できませんでした 1> c:\program files (x86)\microsoft visual studio 9.0\vc\include\xutility(2236) : 'std::operator <' の宣言を確認してください。 のようなエラーが出ます。 しかし、Release版でコンパイルするとコンパイルは通ります。 Debug版でコンパイルを通すにはどのようなコードを追加すればよいでしょうか? 知恵を貸してください。 よろしくおねがいします。 /** VisualStudio2008 AcademiEdition */

  • C++について

    C++の独学初心者です 仕様書?やエラーの見方が全くわかりません 例えば vscodeにてreverse()の関数の説明を見ると以下のような仕様書というのでしょうか?ものが見れますが 私はここからわかるのは返り値がvoidであるということぐらいがだいたい想像できるだけです これはどの様に見れば良いのでしょうか? 解説している様なサイトがあれば教えてください void std::__1::reverse<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>::iterator>(std::__1::__wrap_iter<...> __first, std::__1::__wrap_iter<...> __last) よろしくお願いします

  • cygwinとUnixのコンパイルの違い。

    こんにちは。 UNIXのソースをWindows上でビルドできるようにしています。 Windows上では、cygwinのコンパイラを使用しています。 下記コードがコンパイルが通らず悩んでいます。 vector<TestCls>:: iterator it = &array[2] ; iteratorのitに、arrayの動的配列2番目のアドレスを参照渡し?しています。 UNIXでは、ビルドと動作は確認できたのですが、 CYGWINでは、ビルドができませんでした。 ビルドオプションなど、足りないものがあるのでしょうか? 下記サンプルソースを置きます。 ##################################### ☆☆☆TestCls.h☆☆☆ #ifndef TESTCLS_H_ #define TESTCLS_H_ class TestCls { private: int age ; public : TestCls() ; virtual ~TestCls() ; void setAge(int ax) { age = ax ;} int getAge() { return age ; } } ; #endif /*TESTCLS_H_*/ ##################################### ☆☆☆TestCls.cpp☆☆☆ #include "TestCls.h" TestCls::TestCls() {} TestCls::~TestCls() {} ##################################### ☆☆☆testmain.cpp☆☆☆ #include<vector> #include<iostream> #include "TestCls.h" int main() { using namespace std ; vector<TestCls> array ; int i; for(i=0; i<10; i++) { TestCls clstestCls ; clstestCls.setAge(i+10) ; array.push_back(clstestCls) ; } vector<TestCls>::iterator it = &array[2] ; // ←ここでエラー発生。 while(it != array.end()) { cout << it->getAge() << endl ; ++it ; } return 0 ; } ##################################### ビルドオプションは、 g++ -I"c:\~~\inc" -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/testmain.d" -MT"src/testmain.d" -o"src/testmain.o" "../src/testmain.cpp" エラーメッセージは、 error: conversion from `TestCls*' to non-scalar type `__gnu_cxx::__normal_iterator<TestCls*, std::vector<TestCls, std::allocator<TestCls> > >' requested

  • VisualC++2005にてerror C2664と出ます。STLのpairで引数を変換できないとのことです

    私は現在、VisualC++2005 Express Editionにてプログラミングを行っているのですが、次のようなエラーが出てしまいます。 c:\program files\microsoft visual studio 8\vc\include\utility(44) : error C2664: 'std::pair<_Ty1,_Ty2>::pair(const std::pair<_Ty1,_Ty2> &)' : 1 番目の引数を 'const double' から 'const std::pair<_Ty1,_Ty2> &' に変換できません。(新しい機能 ; ヘルプを参照) with [ _Ty1=double, _Ty2=double ] 理由: 'const double' から 'const std::pair<_Ty1,_Ty2>' へは変換できません。 with [ _Ty1=double, _Ty2=double ] コンストラクタはソース型を持てません、またはコンストラクタのオーバーロードの解決があいまいです。 コードは次のものです。 typedef std::pair<double, double> doublesPair; typedef std::pair<doublesPair, double> posValDouble; typedef std::list<posValDouble> posValDoubleList; ---------------------------------------------------- posValDoubleList::iterator pvdl_ite = pvdl.begin(); Double ax = pvdl_ite->first.first; ay = pvdl_ite->first.second; az = pvdl_ite->second; pvdl_ite++; bx = --- - - - 解決策を教えていただけたらと思います。 よろしくお願いします。

  • C++ vectorのbeginについて

    VC++2010にて下記コードのビルドは通るのですが、 vVecotrInt, vVectorIntPtrの要素数0のとき、iptr代入時に Debug assertaion Failed! vector iterator not dereferencableとなります。 そもそもbegin()はイテレータなので、ポインタに代入しようとしていることが間違いかと思うのですが。 質問1.int* iptr = ~ ではなく、std:vector<int>::iteratorとすれば、     要素数が0でもエラーがおきません。この違いは何でしょうか? 質問2.そもそもイテレータをポインタに代入して何か得することがあるんでしょうか?     ただイテレータとポインタは同じようなものだと思って、コーディングしてるだけなんでしょうか・・・ コード: // vVectorIntの要素を間接参照して(参照先はint)、そのアドレスをポインタに格納 std::vector<int> vVectorInt; int* iptr = &*vVectorInt.begin(); // ここでvector iterator not dereferencable // vVectorIntPtrの要素を間接参照して(参照先はint*)、ポインタに格納 std::vector<int*> vVectorIntPtr; int* iptr = *vVectorIntPtr.begin(); // ここでvector iterator not dereferencable // vVecotrIntPtr2の要素数0のときでも、イテレータを使えば問題ない std::vector<int*> vVectorIntPtr2; std::vector<int*>::iterator itr = vVectorIntPtr2.begin();

  • ファイル読み込みとmap処理

    Visual C++ 2008 Express Edition 環境です。 入力テキストファイルを読み込み、空白で単語を区切り、単語すべてをmapにいれるという処理のプログラムを書こうとしています。 perlでいうところのsplit, 配列へのpushをC++でstrtokとmapでならかけると思いました。 入力ファイルは input1.txt--------------- cat dog mice human mosquito beetle spider ------------------------- プログラムは #include <stdio.h> #include<iostream> #include <map> #include <vector> int main( ) { FILE *input_file1; input_file1 = fopen("input1.txt", "r"); char str[256]; char *token; std::vector<char *> my_vector; // while (fgets(str, 256, input_file1) != NULL) { token = strtok( str , " " ); while( token != NULL ){ my_vector.push_back(token) ; printf("%s\n",token); token = strtok( NULL , " " ); } } printf("starting vector loop\n"); std::vector<char *>::iterator it = my_vector.begin(); // while( it != my_vector.end() ) // { printf("%s\n",*it); ++it; // } fclose(input_file1); return 0; } というふうにしました。 cat dog mice human mosquito beetle spider というような出力がなされるものと思ったのですが、実行してみると mapを使ったループ(全要素)出力は mosquito uito le mosquito beetle spider というふうに出力されてしまいます。 strtokで単語を分ける部分は問題なく出力で確認できるので、問題はmapの作り方やポインタだと思うのですが原因がわかりません。 問題点、解決策がお分かりになる方、よろしくお願いします。