vector<int>型のオブジェクトaのメンバ関数a.endが実行されると最後にメモリに格納されたデータを格納しているアドレスの💖次のアドレス💖が戻り値として返されます      

ソーラー「それでは


次のプログラムをご覧ください

👇

#include <iostream>


#include <vector>


using namespace std;


int main() {


vector<int> a;


int x;


x = 1;

cout<<x<<"\n";

cout<<&x<<"\n";

a.push_back(x);



x = 2;

cout<<x<<"\n";

cout<<&x<<"\n";

a.push_back(x);



x = 3;

cout<<x<<"\n";

cout<<&x<<"\n";

a.push_back(x);


vector<int>::iterator itr = a.begin();


cout << *itr << "\n";


cout << *(itr+1) << "\n";


cout << *(itr+2)<< "\n";


return 0;

}


プログラムの実行結果


1

008FFA54

2

008FFA54

3

008FFA54

1

2

3



ソーラー「このプログラムが実行されると変数xが管理しているメモリとは別の


連続したメモリに


数値データ

1

2

3


が格納されましたね。


そして


イテレータitrを使って


コマンドプロンプト画面に


1

2

3


表示することができました」


マックス「


a.push_back(x);


を使って


メモリに格納されたデータは


イテレータを使わないと


表示できないってところがミソ💖なんだな」


ソーラー「


今度は


これらのメモリに格納されたデータを


もっとかっこよく


コマンドプロンプト画面に表示してみたいと思います


#include <iostream>


#include <vector>


using namespace std;


int main() {


vector<int> a;


int x;


x = 1;

cout << x << "\n";

cout << &x << "\n";

a.push_back(x);



x = 2;

cout << x << "\n";

cout << &x << "\n";

a.push_back(x);



x = 3;

cout << x << "\n";

cout << &x << "\n";

a.push_back(x);



vector<int>::iterator itr = a.begin();




cout << *itr << "\n";


itr++;

cout << *itr << "\n";


itr++;

cout << *itr << "\n";


return 0;

}


ビルド実行結果


1

004FF728

2

004FF728

3

004FF728

1

2

3


ソーラー「さきほどのプログラムを


itr++;


を用いて書き換えてみました」


ぶーにゃん「


あっ これ知ってるニャン


itr++;



itr=itr+1;


を表しているにゃんね」


マックス「ということは


cout << *itr << "\n";


itr++;

cout << *itr << "\n";


itr++;

cout << *itr << "\n";



cout << *itr << "\n";


itr=itr+1;

cout << *(itr) << "\n";


itr=itr+1;

cout << *(itr)<< "\n";



をあらわしているわけだ



itr の値は


itr

itr+1

itr+2

と増加していくので



結局


cout << *itr << "\n";


itr=itr+1;

cout << *(itr) << "\n";


itr=itr+1;

cout << *(itr)<< "\n";



cout << *itr << "\n";


cout << *(itr+1) << "\n";


cout << *(itr+2)<< "\n";


と変形できる


つまり


最初のプログラムの命令文は


cout << *itr << "\n";


cout << *(itr+1) << "\n";


cout << *(itr+2)<< "\n";


になるわけだ」


ソーラー「


そうなんです


そして


cout << *itr << "\n";


itr++;

cout << *(itr) << "\n";


itr++;

cout << *(itr )<< "\n";


さらに

itr++;


をくっつけた



cout << *itr << "\n";


itr++;

cout << *(itr) << "\n";


itr++;

cout << *(itr )<< "\n";


itr++;




while(itr!=a.end()){


cout << *itr << "\n";


itr++;


}


と書き換えることもできます



この

👇

while(itr!=a.end()){


cout << *itr << "\n";


itr++;


}

を用いて


先程のプログラムを書き換えてみます

👇

#include <iostream>


#include <vector>


using namespace std;


int main() {


vector<int> a;


int x;


x = 1;

cout << x << "\n";

cout << &x << "\n";

a.push_back(x);



x = 2;

cout << x << "\n";

cout << &x << "\n";

a.push_back(x);



x = 3;

cout << x << "\n";

cout << &x << "\n";

a.push_back(x);


vector<int>::iterator itr = a.begin();


while (itr != a.end()) {


cout << *itr << "\n";


itr++;


}


return 0;

}


プログラムの実行結果


1

00EFF800

2

00EFF800

3

00EFF800

1

2

3


マックス「


while (itr != a.end()) {


cout << *itr << "\n";


itr++;


}



a.end()が出てくるが


これは


vector<int>型のオブジェクトaのメンバ関数なのか?」



ソーラー「そうなんでえす


a.end();


が実行されると


最後に


a.push_backによってメモリに格納された


数値データ3


を格納しているメモリのアドレスの



      💖さらに次のアドレスが💖



a.end()に戻り値として返されることになります



マックス「???


      💖さらに次のアドレス💖?



ソーラー「そうなんです


この場合



a.push_backによってメモリに格納された


数値データ3


を格納しているメモリのアドレスに


vector<int>のintに対応した4を足したアドレスが


a.end()に戻り値として返されることになります」



マックス「ということは


a.end();


が実行されると


最後に


a.push_backによってメモリに格納された


数値データ3


を格納しているメモリのアドレスが


a.end()の戻り値として返されるんではないってことか


なんかまちがえやすそうな箇所だな」


ソーラー「そうなんです


ぱっと見


一見すると


while (itr != a.end()) {


cout << *itr << "\n";


itr++;


}


itr != a.end()


を見ると


a.end();


が実行されると


最後に


a.push_backによってメモリに格納された


数値データ3


を格納しているメモリのアドレスが


a.end()の戻り値として返される


ようにみえますね


ですが


そうではありません


間違えやすいところです



となると


while (itr != a.end())


のなかの


イテレータitrに格納されるアドレスが


数値データ3


を格納しているメモリのアドレスの次のアドレスに等しくならなければ



while (itr != a.end()){


cout << *itr << "\n";


itr++;


}


のなかの


cout << *itr << "\n";


itr++;



繰り返されることになります」


マックス「ははあ


となると


イテレータitrに格納されるアドレスは


vector<int>::iterator itr = a.begin();


の実行により


最初に


メモリに格納されることになった数値データ1を格納しているメモリのアドレスとなるが


まず


while (itr != a.end()){


cout << *itr << "\n";


itr++;


}


条件式

itr != a.end()が成立する(真の値1をもつ)ので


1回目の


cout << *itr << "\n";


itr++;



実行されると


itrに格納されるアドレスは


数値データ2を格納しているメモリのアドレスとなる


次に


while (itr != a.end()){


cout << *itr << "\n";


itr++;


}


条件式

itr != a.end()が成立する(真の値1をもつ)ので



2回目の


cout << *itr << "\n";


itr++;


が実行されると


イテレータitrに格納されるアドレスは


数値データ3を格納しているメモリのアドレスとなる


そして


while (itr != a.end()){


cout << *itr << "\n";


itr++;


}


条件式

itr != a.end()が成立する(真の値1をもつ)ので



3回目の


cout << *itr << "\n";


itr++;


が実行されると


数値データ3を格納しているメモリのアドレスの



        😊次のアドレス😊



イテレータitr



に格納されることになる


すると


イテレータitr


に格納されたアドレスはa.end()に等しくなり



while (itr != a.end())


のなかの

条件式

itr != a.end()は成立しない(偽の値0をもつ)ので


4回目の


while (itr != a.end()) {


cout << *itr << "\n";


itr++;


}


は実行されないわけだ


なので


コマンドプロンプト画面には


が表示されることになる



なるほどな


なかなか


シンプルなプログラムだが


奥が深いじゃないか?


にゃあ?


ぶーにゃんよ」


ぶーにゃん「にゃにゃ~ん」


int(イント)「猫ちゃんもにゃ~んていってる😊」


ソーラー「


vector<int>::iterator itr = a.end();


が実行されると


最後に


a.push_backによってメモリに格納された


数値データ3


を格納しているメモリのアドレスの



      💖さらに次のアドレスが💖



a.end()に戻り値として返されることになります


そして


イテレータitr


数値データ3


を格納しているメモリのアドレスの



      💖さらに次のアドレスが💖


代入されることになります


この状態で


cout << *itr << "\n";


を実行しようとしても


数値データ3


を格納しているメモリのアドレスの



      💖さらに次のアドレスのメモリ💖



には何もデータが保存されていないので


ビルドエラーが表示されることになります


その時のプログラムはこちらです

👇

  

#include <iostream>


#include <vector>


using namespace std;


int main() {


vector<int> a;


int x;


x = 1;

cout<<x<<"\n";

cout<<&x<<"\n";

a.push_back(x);



x = 2;

cout<<x<<"\n";

cout<<&x<<"\n";

a.push_back(x);



x = 3;

cout<<x<<"\n";

cout<<&x<<"\n";

a.push_back(x);


vector<int>::iterator itr = a.end();


cout << *itr << "\n";


return 0;

}


Debug Assertion Failed!


Program:C\WINDOWS\SYSTEM32\MSVCP140D.dll

File: c:\program files (x86)\microsoft visual

studio\2017\community\vc\tools\msvc\14.11.25503\include\ve

ctor

Line 52


Expression vector iterator not dereferencable


For information onhow your program can cause anassertion

failure,see the Visual C++ documentation on asserts.


(Press Retry to debug the application)

                                          

ソーラー「


真ん中の警告文


Expression vector iterator not dereferencable



そのことを指摘しています」




  • Twitterで共有
  • Facebookで共有
  • はてなブックマークでブックマーク

作者を応援しよう!

ハートをクリックで、簡単に応援の気持ちを伝えられます。(ログインが必要です)

応援したユーザー

応援すると応援コメントも書けます

新規登録で充実の読書を

マイページ
読書の状況から作品を自動で分類して簡単に管理できる
小説の未読話数がひと目でわかり前回の続きから読める
フォローしたユーザーの活動を追える
通知
小説の更新や作者の新作の情報を受け取れる
閲覧履歴
以前読んだ小説が一覧で見つけやすい
新規ユーザー登録無料

アカウントをお持ちの方はログイン

カクヨムで可能な読書体験をくわしく知る