C++編で扱っている C++ は 2003年に登場した C++03
という、とても古いバージョンのものです。C++ はその後、C++11 -> C++14
-> C++17 -> C++20 -> C++23 と更新されています。
なかでも C++11 での更新は非常に大きなものであり、これから C++
の学習を始めるのなら、C++11
よりも古いバージョンを対象にするべきではありません。特に事情がないなら、新しい
C++ を学んでください。 当サイトでは、C++14 をベースにした新C++編を作成中です。
問題① あなたの使っているコンパイラにおいて、空の vector はどれだけのサイズと容量を持つか調べてみてください。
簡単な実験プログラムを書いて確かめてみましょう。
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v;
std::cout << "size: " << v.size() << std::endl;
std::cout << "capa: " << v.capacity() << std::endl;
}
実行結果:
0
0
空の vector を生成した直後は、「サイズ」も「容量」も 0 になります。string では、実装によって「容量」の方は 1以上の大きさを持ちますが、vector は必ず 0 です。
問題② 次のプログラムには、vector の使い方に関するいくつかの問題が潜んでいます。指摘してください。
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v;
[3] = 3;
v
.resize(100);
v
int* p = &v[10];
.insert(v.begin(), 200);
v
*p = 10;
}
v は、空の状態で生成されているため「サイズ」は 0 です。したがって、その直後に「v[3] = 3;」のようなアクセスは、範囲外アクセスになってしまいます。添字演算子では、push_backメンバ関数のような、領域の拡張は行われないことに注意してください。
内部要素のメモリアドレスを、ポインタ変数 p に取得した後、insertメンバ関数で要素を挿入しています。要素が挿入されると、後続の要素のメモリアドレスがずれることになるため、イテレータやポインタは無効になります。そのため、この後「*p = 10;」としている部分にも問題があります。
問題③ この章のサンプルプログラム内で何度か登場した PrintVector関数を、イテレータを使った方法で書き直してください。
vector は、配列の代わりとして使うという役割もあるので一概には言えませんが、他の STLコンテナとのコードの統一や、STLアルゴリズムを使うことを考えると、できるだけイテレータを使うのが良いかもしれません。
#include <iostream>
#include <vector>
typedef std::vector<int> IntVector;
void PrintVector(const IntVector& v)
{
const IntVector::const_iterator itEnd = v.end();
for (IntVector::const_iterator it = v.begin(); it != itEnd; ++it) {
std::cout << *it << "\n";
}
std::cout << std::endl;
}
int main()
{
(10, 3);
IntVector v
(v);
PrintVector}
実行結果:
3
3
3
3
3
3
3
3
3
3
const_iterator の存在を忘れないようにしましょう。指している先の要素を書き換える必要がないのならば、const_iterator を使えます。C++プログラミングの基本に従って、しっかりと const を活用してください(【言語解説】第15章)。
新規作成。
Programming Place Plus のトップページへ
はてなブックマーク に保存 | Pocket に保存 | Facebook でシェア |
X で ポスト/フォロー | LINE で送る | noteで書く |
RSS | 管理者情報 | プライバシーポリシー |