[C++] STLのstd::arrayの使い方について詳しく解説
C++のSTLに含まれるstd::array
は、固定サイズの配列を扱うためのコンテナで、静的メモリを使用します。
サイズはコンパイル時に決定され、動的なリサイズはできません。
std::array
は通常の配列と異なり、メンバ関数を持ち、STLアルゴリズムと互換性があります。
宣言時にはstd::array<型, サイズ>
を使用します。
要素へのアクセスはat()
(範囲外チェックあり)や[]
で行い、size()
で要素数を取得可能です。
また、begin()
やend()
でイテレータを取得し、範囲for文やアルゴリズムに利用できます。
std::arrayとは何か
std::array
は、C++11で導入された固定サイズの配列を表すコンテナです。
C言語の配列と似ていますが、いくつかの利点があります。
std::array
は、STL(Standard Template Library)の一部であり、型安全性や便利なメンバ関数を提供します。
以下に、std::array
の特徴を示します。
特徴 | 説明 |
---|---|
固定サイズ | サイズはコンパイル時に決定され、変更不可 |
型安全性 | 要素の型を指定でき、型の不一致を防ぐ |
STLとの互換性 | STLアルゴリズムと簡単に連携できる |
メンバ関数の利用 | size() , at() , fill() などが利用可能 |
std::array
は、C++の標準ライブラリに含まれているため、特別なライブラリをインクルードすることなく使用できます。
これにより、配列の操作がより簡単かつ安全になります。
次のセクションでは、std::array
の宣言と初期化について詳しく見ていきます。
std::arrayの宣言と初期化
std::array
の宣言は、C++のテンプレートを使用して行います。
宣言時に要素の型と配列のサイズを指定する必要があります。
以下に、std::array
の基本的な宣言と初期化の方法を示します。
基本的な宣言
#include <array>
#include <iostream>
int main() {
// 整数型のstd::arrayを宣言
std::array<int, 5> myArray; // サイズ5の配列
return 0;
}
初期化の方法
std::array
は、宣言時に初期化することができます。
以下の方法で初期化が可能です。
- リスト初期化
#include <array>
#include <iostream>
int main() {
// リスト初期化を使用して宣言と同時に初期化
std::array<int, 5> myArray = {1, 2, 3, 4, 5};
// 配列の要素を表示
for (const auto& element : myArray) {
std::cout << element << " "; // 要素を表示
}
return 0;
}
1 2 3 4 5
- デフォルト初期化
#include <array>
#include <iostream>
int main() {
// デフォルト初期化
std::array<int, 5> myArray{}; // すべての要素が0で初期化される
// 配列の要素を表示
for (const auto& element : myArray) {
std::cout << element << " "; // 要素を表示
}
return 0;
}
0 0 0 0 0
std::array
は、リスト初期化やデフォルト初期化を使用して簡単に宣言・初期化が可能です。
これにより、配列の初期化がより直感的かつ安全に行えます。
次のセクションでは、std::array
の要素アクセス方法について詳しく解説します。
std::arrayの要素アクセス方法
std::array
の要素には、いくつかの方法でアクセスすることができます。
これにより、配列の要素を簡単に取得したり、変更したりすることが可能です。
以下に、主な要素アクセス方法を示します。
1. インデックス演算子を使用したアクセス
インデックス演算子[]
を使用して、要素にアクセスすることができます。
インデックスは0から始まります。
#include <array>
#include <iostream>
int main() {
std::array<int, 5> myArray = {10, 20, 30, 40, 50};
// インデックス演算子を使用して要素にアクセス
std::cout << "要素1: " << myArray[0] << std::endl; // 10
std::cout << "要素2: " << myArray[1] << std::endl; // 20
// 要素の変更
myArray[2] = 100;
std::cout << "変更後の要素3: " << myArray[2] << std::endl; // 100
return 0;
}
要素1: 10
要素2: 20
変更後の要素3: 100
2. at()メンバ関数を使用したアクセス
at()
メンバ関数を使用すると、範囲外アクセス時に例外がスローされるため、安全に要素にアクセスできます。
#include <array>
#include <iostream>
int main() {
std::array<int, 5> myArray = {10, 20, 30, 40, 50};
// at()メンバ関数を使用して要素にアクセス
std::cout << "要素1: " << myArray.at(0) << std::endl; // 10
std::cout << "要素2: " << myArray.at(1) << std::endl; // 20
// 要素の変更
myArray.at(3) = 200;
std::cout << "変更後の要素4: " << myArray.at(3) << std::endl; // 200
// 範囲外アクセス(例外がスローされる)
// std::cout << myArray.at(5); // 例外が発生する
return 0;
}
要素1: 10
要素2: 20
変更後の要素4: 200
3. front()およびback()メンバ関数を使用したアクセス
front()
メンバ関数は最初の要素を、back()
メンバ関数は最後の要素を取得します。
#include <array>
#include <iostream>
int main() {
std::array<int, 5> myArray = {10, 20, 30, 40, 50};
// front()とback()を使用して要素にアクセス
std::cout << "最初の要素: " << myArray.front() << std::endl; // 10
std::cout << "最後の要素: " << myArray.back() << std::endl; // 50
return 0;
}
最初の要素: 10
最後の要素: 50
std::array
の要素には、インデックス演算子、at()
メンバ関数、front()
およびback()
メンバ関数を使用してアクセスできます。
これにより、要素の取得や変更が簡単に行えます。
次のセクションでは、std::array
のメンバ関数について詳しく解説します。
std::arrayのメンバ関数
std::array
は、いくつかの便利なメンバ関数を提供しており、配列の操作を簡単に行うことができます。
以下に、主なメンバ関数を紹介します。
1. size()
size()
メンバ関数は、配列の要素数を返します。
固定サイズの配列であるため、常に同じ値を返します。
#include <array>
#include <iostream>
int main() {
std::array<int, 5> myArray = {1, 2, 3, 4, 5};
// size()メンバ関数を使用して要素数を取得
std::cout << "配列の要素数: " << myArray.size() << std::endl; // 5
return 0;
}
配列の要素数: 5
2. fill()
fill()
メンバ関数は、配列のすべての要素を指定した値で埋めることができます。
#include <array>
#include <iostream>
int main() {
std::array<int, 5> myArray;
// fill()メンバ関数を使用してすべての要素を0で埋める
myArray.fill(0);
// 配列の要素を表示
for (const auto& element : myArray) {
std::cout << element << " "; // 0 0 0 0 0
}
return 0;
}
0 0 0 0 0
3. at()
at()
メンバ関数は、指定したインデックスの要素にアクセスします。
範囲外のインデックスを指定すると、例外がスローされるため、安全に使用できます。
#include <array>
#include <iostream>
int main() {
std::array<int, 5> myArray = {10, 20, 30, 40, 50};
// at()メンバ関数を使用して要素にアクセス
std::cout << "要素3: " << myArray.at(2) << std::endl; // 30
return 0;
}
要素3: 30
4. front() と back()
front()
メンバ関数は最初の要素を、back()
メンバ関数は最後の要素を取得します。
#include <array>
#include <iostream>
int main() {
std::array<int, 5> myArray = {10, 20, 30, 40, 50};
// front()とback()を使用して要素にアクセス
std::cout << "最初の要素: " << myArray.front() << std::endl; // 10
std::cout << "最後の要素: " << myArray.back() << std::endl; // 50
return 0;
}
最初の要素: 10
最後の要素: 50
5. data()
data()
メンバ関数は、配列の先頭要素へのポインタを返します。
これにより、配列のデータをCスタイルの配列として扱うことができます。
#include <array>
#include <iostream>
int main() {
std::array<int, 5> myArray = {1, 2, 3, 4, 5};
// data()メンバ関数を使用して配列の先頭要素へのポインタを取得
int* pData = myArray.data();
// ポインタを使用して要素を表示
for (size_t i = 0; i < myArray.size(); ++i) {
std::cout << pData[i] << " "; // 1 2 3 4 5
}
return 0;
}
1 2 3 4 5
std::array
のメンバ関数を使用することで、配列の要素数の取得、要素の初期化、要素への安全なアクセスなどが簡単に行えます。
次のセクションでは、std::array
とSTLアルゴリズムの連携について詳しく解説します。
std::arrayとSTLアルゴリズムの連携
std::array
は、STL(Standard Template Library)のアルゴリズムと簡単に連携できるため、配列の操作が非常に便利になります。
STLアルゴリズムを使用することで、ソートや検索、変換などの操作を簡潔に行うことができます。
以下に、いくつかの代表的なアルゴリズムの使用例を示します。
1. std::sortによるソート
std::sort
を使用して、std::array
の要素をソートすることができます。
#include <array>
#include <algorithm> // std::sort
#include <iostream>
int main() {
std::array<int, 5> myArray = {5, 3, 1, 4, 2};
// std::sortを使用して配列をソート
std::sort(myArray.begin(), myArray.end());
// ソート後の要素を表示
for (const auto& element : myArray) {
std::cout << element << " "; // 1 2 3 4 5
}
return 0;
}
1 2 3 4 5
2. std::findによる検索
std::find
を使用して、std::array
内の特定の要素を検索することができます。
#include <array>
#include <algorithm> // std::find
#include <iostream>
int main() {
std::array<int, 5> myArray = {10, 20, 30, 40, 50};
// std::findを使用して要素を検索
auto it = std::find(myArray.begin(), myArray.end(), 30);
if (it != myArray.end()) {
std::cout << "要素30が見つかりました。" << std::endl; // 要素30が見つかりました。
} else {
std::cout << "要素30は見つかりませんでした。" << std::endl;
}
return 0;
}
要素30が見つかりました。
3. std::for_eachによる要素の操作
std::for_each
を使用して、配列の各要素に対して操作を行うことができます。
#include <array>
#include <algorithm> // std::for_each
#include <iostream>
int main() {
std::array<int, 5> myArray = {1, 2, 3, 4, 5};
// std::for_eachを使用して要素を2倍にする
std::for_each(myArray.begin(), myArray.end(), [](int& element) {
element *= 2; // 要素を2倍にする
});
// 変更後の要素を表示
for (const auto& element : myArray) {
std::cout << element << " "; // 2 4 6 8 10
}
return 0;
}
2 4 6 8 10
4. std::accumulateによる合計の計算
std::accumulate
を使用して、配列の要素の合計を計算することができます。
#include <array>
#include <numeric> // std::accumulate
#include <iostream>
int main() {
std::array<int, 5> myArray = {1, 2, 3, 4, 5};
// std::accumulateを使用して合計を計算
int sum = std::accumulate(myArray.begin(), myArray.end(), 0);
std::cout << "合計: " << sum << std::endl; // 合計: 15
return 0;
}
合計: 15
std::array
は、STLアルゴリズムと連携することで、配列の操作が非常に簡単になります。
ソート、検索、要素の操作、合計の計算など、さまざまな操作を効率的に行うことができます。
次のセクションでは、std::array
の応用例について詳しく解説します。
std::arrayの応用例
std::array
は、固定サイズの配列を扱うための便利なコンテナであり、さまざまな場面で応用できます。
以下に、std::array
の具体的な応用例をいくつか紹介します。
1. 2次元配列の実装
std::array
を使用して、2次元配列を簡単に実装することができます。
以下の例では、3×3の行列を作成し、要素を表示します。
#include <array>
#include <iostream>
int main() {
// 3x3の行列をstd::arrayで定義
std::array<std::array<int, 3>, 3> matrix = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}};
// 行列の要素を表示
for (const auto& row : matrix) {
for (const auto& element : row) {
std::cout << element << " "; // 1 2 3 4 5 6 7 8 9
}
std::cout << std::endl;
}
return 0;
}
1 2 3
4 5 6
7 8 9
2. スタックの実装
std::array
を使用して、スタック(LIFO)を実装することができます。
以下の例では、スタックの基本的な操作を示します。
#include <array>
#include <iostream>
#include <stdexcept> // std::runtime_error
template <typename T, std::size_t N>
class Stack {
private:
std::array<T, N> data; // スタックのデータ
std::size_t topIndex; // スタックのトップインデックス
public:
Stack() : topIndex(0) {} // コンストラクタ
void push(const T& value) {
if (topIndex >= N) {
throw std::runtime_error("スタックが満杯です。");
}
data[topIndex++] = value; // 値を追加
}
T pop() {
if (topIndex == 0) {
throw std::runtime_error("スタックが空です。");
}
return data[--topIndex]; // 値を取り出す
}
bool isEmpty() const {
return topIndex == 0; // スタックが空かどうか
}
};
int main() {
Stack<int, 5> myStack; // 整数型のスタックを作成
myStack.push(1);
myStack.push(2);
myStack.push(3);
std::cout << "ポップした値: " << myStack.pop() << std::endl; // 3
std::cout << "ポップした値: " << myStack.pop() << std::endl; // 2
return 0;
}
ポップした値: 3
ポップした値: 2
3. 簡単な統計処理
std::array
を使用して、データの平均値や中央値を計算する簡単な統計処理を行うことができます。
以下の例では、平均値を計算します。
#include <array>
#include <iostream>
#include <numeric> // std::accumulate
int main() {
std::array<double, 5> data = {10.0, 20.0, 30.0, 40.0, 50.0};
// 平均値を計算
double sum = std::accumulate(data.begin(), data.end(), 0.0);
double average = sum / data.size();
std::cout << "平均値: " << average << std::endl; // 平均値: 30
return 0;
}
平均値: 30
4. グラフの隣接リストの実装
std::array
を使用して、グラフの隣接リストを実装することも可能です。
以下の例では、簡単な無向グラフを表現します。
#include <array>
#include <iostream>
#include <vector> // std::vector
const int V = 5; // 頂点の数
class Graph {
private:
std::array<std::vector<int>, V> adjList; // 隣接リスト
public:
void addEdge(int u, int v) {
adjList[u].push_back(v); // 辺を追加
adjList[v].push_back(u); // 無向グラフなので逆方向も追加
}
void printGraph() const {
for (int i = 0; i < V; ++i) {
std::cout << "頂点 " << i << ": ";
for (const auto& vertex : adjList[i]) {
std::cout << vertex << " "; // 隣接頂点を表示
}
std::cout << std::endl;
}
}
};
int main() {
Graph g;
g.addEdge(0, 1);
g.addEdge(0, 4);
g.addEdge(1, 2);
g.addEdge(1, 3);
g.addEdge(1, 4);
g.addEdge(2, 3);
g.addEdge(3, 4);
g.printGraph(); // グラフを表示
return 0;
}
頂点 0: 1 4
頂点 1: 0 2 3 4
頂点 2: 1 3
頂点 3: 1 2 4
頂点 4: 0 1 3
std::array
は、さまざまな場面で応用可能な強力なコンテナです。
2次元配列の実装、スタックの作成、統計処理、グラフの隣接リストの実装など、さまざまなデータ構造やアルゴリズムに利用できます。
まとめ
この記事では、C++のstd::array
について、その基本的な使い方から応用例まで幅広く解説しました。
std::array
は、固定サイズの配列を扱うための便利なコンテナであり、STLアルゴリズムとの連携により、さまざまな操作が簡単に行えることがわかりました。
これを機に、std::array
を活用して、より効率的なプログラミングを実践してみてはいかがでしょうか。