08_配列とベクタの使い方

はじめに

複数のデータをまとめて管理・操作するための「配列」と「ベクタ」について学びます。配列はC言語でもおなじみですが、C++では「ベクタ(vector)」という便利な仕組みもあります。

ベクタ(vector)とは

C++標準ライブラリに用意された 可変長の配列です。

vector<int> nums = {1, 2, 3, 4};  // これは変数名。ベクタ変数と呼びます。

配列とベクタの違い・使い分け

比較項目 配列 ベクタ (vector)
サイズ 固定 可変(動的に増減)
メモリ管理 手動 自動
初期化 軽量・高速 やや重い(柔軟性あり)
安全性 範囲外アクセスに弱い .at() で安全にアクセス
実行速度 高速 少しだけオーバーヘッドあり

配列が向いている場面:サイズが固定・高速な処理・シンプルな構造

ベクタが向いている場面:要素数が途中で変わる・安全性や柔軟性を重視・標準ライブラリの機能を活用したい

ベクタの基本操作

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> scores = {10, 20, 30, 40, 50};
    scores.push_back(60);

    for (int i = 0; i < scores.size(); i++) {
        cout << scores[i] << endl;
    }
    return 0;
}

ベクタの宣言方法

vector<int> a;             // 空のベクタ
vector<int> b(5);          // 要素数5、全て0で初期化
vector<int> c(5, 10);      // 要素数5、全て10で初期化
vector<int> d = {1, 2, 3}; // リスト初期化

よく使うメンバ関数

機能 書き方例 説明
要素の追加 vec.push_back(値) 末尾に要素を追加
要素数の取得 vec.size() 要素数を返す
要素の削除(末尾) vec.pop_back() 最後の要素を削除
全要素削除 vec.clear() ベクタを空にする
空かどうか判定 vec.empty() 要素が空ならtrue
要素アクセス vec[i]vec.at(i) atは範囲外アクセス時に例外が発生する
初期化 vec.assign(3, 100) 3個の100で初期化

ベクタの内部構造について(概念解説)

vector オブジェクトの内部には次の情報が含まれています:実データへのポインタ、要素数(size())、確保済み容量(capacity())。

push_back() による追加は、容量の範囲内なら再確保されずに高速。容量を超えたときにのみ、新しいメモリ領域が確保されてコピーされます。

配列の例

#include <iostream>
using namespace std;

int main() {
    int nums[3] = {1, 2, 3};

    for (int i = 0; i < 3; i++) {
        cout << nums[i] << endl;
    }
    return 0;
}

コーディング演習

演習1:基本コードを動かす

08_01_vector.cpp を作成し、次のコードを入力して実行しましょう。
// vector_basic.cpp
#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> scores = {10, 20, 30, 40, 50};
    scores.push_back(60);

    for (int i = 0; i < scores.size(); i++) {
        cout << scores[i] << endl;
    }
    return 0;
}

演習2:コードを改造する

08_01_vector.cpp をコピーして 08_02_vector_mod.cpp として保存し、次の変更を加えてみましょう:
ヒントを見る 合計を求めるには int sum = 0; を宣言し、ループ内で sum += scores[i]; と加算します。
scores.pop_back();for ループの前に呼ぶと最後の要素が削除されます。

理解度チェック

問題08-1

次のコードを実行したとき、vec.size() の値はいくつですか?

vector<int> vec = {10, 20, 30};
vec.push_back(40);
解説を表示 正解:イ
最初に3つの要素で初期化し、push_back(40) で1つ追加したので要素数は4になります。

問題08-2

次のコードを実行した後の vec の要素数はいくつですか?

vector<int> vec = {1, 2, 3, 4, 5};
vec.pop_back();
vec.pop_back();
解説を表示 正解:ウ
pop_back() は末尾の要素を1つ削除します。2回呼ぶと5-2=3要素になります。

問題08-3

配列とベクタの違いとして正しいものはどれですか?

解説を表示 正解:ア
ベクタは可変長で、push_back() などで動的に要素を追加できます。配列はサイズが宣言時に固定されます。

問題08-4

次のコードを実行すると何が表示されますか?

vector<int> v(3, 10);
cout << v[1] << endl;
解説を表示 正解:ウ
vector<int> v(3, 10) は「要素数3、全要素の初期値10」のベクタを作ります。v[1] はインデックス1の要素なので10が表示されます。

補足:範囲for文(拡張for文)プレビュー

vector の全要素を順に処理するとき、インデックスを使わない書き方があります。 これを 範囲for文(range-based for) といいます。

// 通常のfor文(インデックス使用)
for (int i = 0; i < nums.size(); i++) {
    cout << nums[i] << endl;
}

// 範囲for文(すっきり書ける)
for (int n : nums) {
    cout << n << endl;
}
コロン(:)の読み方: for (int n : nums) は「nums の各要素を n として処理する」と読みます。 要素を変更したい場合や大きなオブジェクトを扱う場合は int& n(参照)を使いますが、 詳しくは 18章(拡張for文とイテレータ) で扱います。

まとめ