C++/配列とベクトル
配列とベクトルの基本概念
[編集]配列とベクトルの定義と基本的な使い方
[編集]配列とベクトルは、複数の要素を格納するための主要なデータ構造です。配列は固定サイズの連続したメモリ領域に要素を格納し、要素の追加や削除が困難です。一方、ベクトルは動的にメモリを確保し、要素の追加や削除が容易です。例えば、整数の配列を定義する場合、以下のように記述します。
int array[5]; // 5つの整数を格納する配列
ベクトルを使用する場合、標準ライブラリの std::vector
クラスを利用します。
#include <vector> std::vector<int> vec; // 整数を格納するベクトル
C++20における標準ライブラリの配列とベクトルの導入
[編集]C++20では、標準ライブラリがさらに強化され、配列とベクトルの操作がより便利になりました。例えば、std::erase
や std::erase_if
を使用することで、ベクトルから特定の要素を削除することができます。
#include <vector> #include <algorithm> std::vector<int> vec = {1, 2, 3, 4, 5}; vec.erase(std::remove(vec.begin(), vec.end(), 3), vec.end()); // 3を削除
配列の操作
[編集]配列の宣言と初期化
[編集]配列を宣言する際には、その要素の型とサイズを指定します。また、初期化を行うこともできます。
int array[5] = {1, 2, 3, 4, 5}; // 要素が1から5までの整数で初期化された配列
配列要素へのアクセス
[編集]配列の要素には、インデックスを使用してアクセスします。インデックスは0から始まります。
int x = array[2]; // 配列の3番目の要素にアクセス
配列の要素の追加と削除
[編集]配列のサイズは宣言時に固定されるため、要素の追加や削除は困難です。要素を削除したい場合は、代わりに該当する要素を無効な値で置き換えることが一般的です。
array[2] = 0; // 配列の3番目の要素を無効な値で置き換えることで削除
ベクトルの操作
[編集]ベクトルの宣言と初期化
[編集]ベクトルを宣言する際には、std::vector
クラスを使用し、必要に応じて初期化リストを指定します。
- 初期化リストによる std
- :vecttor の初期化
#include <vector> std::vector<int> vec1 = {1, 2, 3, 4, 5}; // 要素が1から5までの整数で初期化されたベクトル
- C++17からは型推論が可能
auto vec2 = std::vector{1, 2, 3, 4, 5}; // 要素が1から5までの整数で初期化されたベクトル
ベクトル要素へのアクセス
[編集]ベクトルの要素にも、配列と同様にインデックスを使用してアクセスします。
int y = vec[2]; // ベクトルの3番目の要素にアクセス
ベクトルの要素の追加と削除
[編集]ベクトルは動的にサイズが変更できるため、要素の追加や削除が容易です。
vec.push_back(6); // ベクトルの末尾に要素を追加 vec.pop_back(); // ベクトルの末尾の要素を削除
---
このようにして、配列とベクトルの基本的な操作方法を理解しました。次のセクションでは、より高度な操作や実践的な応用について掘り下げていきます。
範囲ベースのforループとアルゴリズム
[編集]範囲ベースのforループの使用法
[編集]C++11から導入された範囲ベースのforループを使用することで、配列やベクトルの要素に簡単にアクセスできます。
// 配列の場合 for (int elem : array) { // elemを処理 } // ベクトルの場合 for (int elem : vec) { // elemを処理 }
標準ライブラリのアルゴリズムの配列やベクトルへの適用
[編集]標準ライブラリには、配列やベクトルなどのコンテナに対して便利なアルゴリズムが含まれています。これらのアルゴリズムを活用することで、効率的なコードを記述できます。
#include <algorithm> // 配列やベクトルの要素をソートする std::sort(vec.begin(), vec.end()); // 配列やベクトルから特定の要素を検索する auto it = std::find(vec.begin(), vec.end(), 3); if (it != vec.end()) { // 見つかった場合の処理 }
多次元配列
[編集]二次元配列の宣言と操作
[編集]多次元配列は、配列の配列やベクトルのベクトルとして宣言されます。二次元配列の場合、行と列の2次元のインデックスを使用して要素にアクセスします。
int matrix[3][3]; // 3x3の二次元配列 matrix[1][2] = 5; // 2行目、3列目の要素にアクセスして値を設定
C++20のstd::spanを使った多次元配列の取り扱い
[編集]C++20では、std::span
を使用することで、多次元配列をより効率的に扱うことができます。
#include <span> std::span<int, 3> row = matrix[1]; // 2行目の要素をspanとして取得 row[2] = 5; // 2行目、3列目の要素にアクセスして値を設定
---
このようにして、範囲ベースのforループや標準ライブラリのアルゴリズム、そして多次元配列の取り扱いについて学びました。次のセクションでは、さらに高度な操作や実践的なプロジェクトを取り上げていきます。
ベクトルと配列の比較
[編集]ベクトルと配列の性能比較
[編集]配列とベクトルは、それぞれ異なる性質を持っています。配列は静的なサイズを持ち、要素の追加や削除が困難ですが、ランダムアクセスが高速です。一方、ベクトルは動的にサイズが変更でき、要素の追加や削除が容易ですが、ランダムアクセスは配列よりも遅い場合があります。
使用状況に応じた適切なデータ構造の選択
[編集]プログラムの要件や使用状況に応じて、配列とベクトルのどちらを使用するかを適切に選択することが重要です。例えば、要素数が固定である場合やランダムアクセスが頻繁に行われる場合は配列を使用し、要素の追加や削除が頻繁に行われる場合はベクトルを使用することが適しています。
ベクトルと配列の高度な操作
[編集]ベクトルや配列のソート
[編集]標準ライブラリには、ベクトルや配列をソートするためのさまざまなアルゴリズムが含まれています。これらのアルゴリズムを活用することで、効率的にソートを行うことができます。
#include <algorithm> std::sort(vec.begin(), vec.end()); // ベクトルの要素を昇順にソート
ベクトルや配列の検索
[編集]標準ライブラリには、ベクトルや配列から特定の要素を検索するためのアルゴリズムも含まれています。
#include <algorithm> auto it = std::find(vec.begin(), vec.end(), 3); // ベクトルから値が3の要素を検索 if (it != vec.end()) { // 見つかった場合の処理 }
ベクトルや配列の操作における効率的な手法
[編集]効率的なプログラミングを行うためには、ベクトルや配列の操作において適切な手法を選択することが重要です。例えば、ランダムアクセスが必要な場合はインデックスを使用し、範囲ベースのforループを使用することでシンプルで読みやすいコードを記述することができます。
配列とstd::vectorの中間の性質を持ったstd::array
[編集]std::array
は、C++11から導入された固定長の配列クラスです。配列とstd::vector
の中間の性質を備えています。
// 要素数10の整数型std::arrayの宣言 std::array<int, 10> arr; // 初期値を指定して宣言 std::array<int, 5> arr = {1, 2, 3, 4, 5}; // C++17からは要素型と要素数が推論が可能 auto arr = std::array{1, 2, 3, 4, 5};
std::array
の主な特徴は以下の通りです。
- 配列と共通の性質
- 固定長であり、実行時に要素数を変更できない
- 要素へのアクセスが高速
- コンパイル時に要素数が確定している
std::vector
と共通の性質- イテレータによるアクセスが可能
at()
メソッドによる範囲チェック付きのアクセスが可能begin()
、end()
メソッドを持つsize()
メソッドで要素数を取得できる- 値の代入や
fill()
メソッドによる一括代入ができる - デフォルトコンストラクタでゼロ初期化される
- その他の特徴
- C++17以降では
std::array
にstd::swapを使える std::get<N>(arr)
でN番目の要素を取得できる- C++20以降では
std::array
にstd::sortや std::rangeアクセサを使える
std::array
は、要素数の固定長性と、イテレーションやアクセス範囲チェックなどの安全性を兼ね備えています。小規模のデータ構造に適しています。std::vector
のようにリサイズはできませんが、std::array
は単一の連続したメモリブロックに格納されるため、メモリ効率が良く高速です。