🌻天国にいけるC++言語入門🌻 進化し続けるオブジェクト指向プログラミング ver3.2307
vector<int>型のオブジェクトaのメンバ関数a.endが実行されると最後にメモリに格納されたデータを格納しているアドレスの💖次のアドレス💖が戻り値として返されます
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++;
}
は実行されないわけだ
なので
コマンドプロンプト画面には
1
2
3
が表示されることになる
なるほどな
なかなか
シンプルなプログラムだが
奥が深いじゃないか?
にゃあ?
ぶーにゃんよ」
ぶーにゃん「にゃにゃ~ん」
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
が
そのことを指摘しています」
新規登録で充実の読書を
- マイページ
- 読書の状況から作品を自動で分類して簡単に管理できる
- 小説の未読話数がひと目でわかり前回の続きから読める
- フォローしたユーザーの活動を追える
- 通知
- 小説の更新や作者の新作の情報を受け取れる
- 閲覧履歴
- 以前読んだ小説が一覧で見つけやすい
アカウントをお持ちの方はログイン
ビューワー設定
文字サイズ
背景色
フォント
組み方向
機能をオンにすると、画面の下部をタップする度に自動的にスクロールして読み進められます。
応援すると応援コメントも書けます