[C++] 配列を関数の引数として渡す方法
C++では、配列を関数の引数として渡す際に、配列のポインタを使用することが一般的です。
関数のパラメータとして配列を受け取る場合、配列の要素数を指定することはできませんが、ポインタを使って配列の先頭アドレスを渡すことができます。
この方法により、関数内で配列の要素にアクセスすることが可能です。
また、配列のサイズを関数内で使用する場合は、別途サイズを引数として渡す必要があります。
- 配列を関数に渡す際のポインタと参照の使い方
- std::arrayとstd::vectorを用いた配列の渡し方と返し方
- 多次元配列や部分配列を関数に渡す方法
- 配列を使ったソートや探索アルゴリズムの実装例
配列を関数に渡す方法
C++では、配列を関数に渡す方法がいくつかあります。
それぞれの方法には利点と注意点があり、用途に応じて使い分けることが重要です。
以下では、配列を関数に渡す方法について詳しく解説します。
配列のポインタを渡す
ポインタを使った配列の渡し方
配列を関数に渡す最も一般的な方法は、配列の先頭要素のポインタを渡すことです。
以下にその例を示します。
#include <iostream>
// 配列をポインタで受け取る関数
void printArray(int* array, int size) {
for (int i = 0; i < size; ++i) {
std::cout << array[i] << " ";
}
std::cout << std::endl;
}
int main() {
int numbers[] = {1, 2, 3, 4, 5};
int size = sizeof(numbers) / sizeof(numbers[0]);
printArray(numbers, size); // 配列の先頭アドレスを渡す
return 0;
}
1 2 3 4 5
この方法では、配列の先頭アドレスを渡すことで、関数内で配列の要素にアクセスできます。
ポインタを使う際の注意点
- 配列のサイズ情報は別途渡す必要があります。
ポインタだけでは配列のサイズを知ることができません。
- 配列の要素数が固定されていない場合、誤ったサイズを渡すとバッファオーバーランの原因になります。
配列の参照を渡す
参照を使った配列の渡し方
C++11以降では、配列を参照として渡すことも可能です。
これにより、配列のサイズをコンパイル時に固定することができます。
#include <iostream>
// 配列を参照で受け取る関数
template <size_t N>
void printArray(const int (&array)[N]) {
for (size_t i = 0; i < N; ++i) {
std::cout << array[i] << " ";
}
std::cout << std::endl;
}
int main() {
int numbers[] = {1, 2, 3, 4, 5};
printArray(numbers); // 配列を参照で渡す
return 0;
}
1 2 3 4 5
この方法では、配列のサイズがテンプレート引数として渡されるため、サイズ情報を別途渡す必要がありません。
参照を使う際の注意点
- 配列のサイズが固定されるため、異なるサイズの配列を同じ関数に渡すことはできません。
- テンプレートを使用するため、コンパイル時にコードが展開され、バイナリサイズが増加する可能性があります。
std::arrayを使った方法
std::arrayの基本
std::array
は、C++11で導入された固定サイズの配列を扱うためのコンテナです。
std::array
は、配列のサイズをテンプレート引数として指定します。
#include <iostream>
#include <array>
int main() {
std::array<int, 5> numbers = {1, 2, 3, 4, 5};
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
1 2 3 4 5
std::array
は、配列のサイズをコンパイル時に固定し、要素数を超えるアクセスを防ぎます。
std::arrayを関数に渡す方法
std::array
を関数に渡す際は、通常のオブジェクトと同様に参照を使うことが一般的です。
#include <iostream>
#include <array>
// std::arrayを参照で受け取る関数
void printArray(const std::array<int, 5>& array) {
for (int num : array) {
std::cout << num << " ";
}
std::cout << std::endl;
}
int main() {
std::array<int, 5> numbers = {1, 2, 3, 4, 5};
printArray(numbers); // std::arrayを参照で渡す
return 0;
}
1 2 3 4 5
この方法では、std::array
のサイズが固定されているため、サイズ情報を別途渡す必要がありません。
std::vectorを使った方法
std::vectorの基本
std::vector
は、可変長の配列を扱うためのコンテナです。
要素の追加や削除が容易で、動的にサイズを変更できます。
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
numbers.push_back(6); // 要素を追加
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
1 2 3 4 5 6
std::vector
は、動的にサイズを変更できるため、柔軟な配列操作が可能です。
std::vectorを関数に渡す方法
std::vector
を関数に渡す際は、通常のオブジェクトと同様に参照を使うことが一般的です。
#include <iostream>
#include <vector>
// std::vectorを参照で受け取る関数
void printVector(const std::vector<int>& vec) {
for (int num : vec) {
std::cout << num << " ";
}
std::cout << std::endl;
}
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
printVector(numbers); // std::vectorを参照で渡す
return 0;
}
1 2 3 4 5
この方法では、std::vector
のサイズを動的に変更できるため、柔軟な配列操作が可能です。
配列を関数から返す方法
C++では、関数から配列を返す方法がいくつかあります。
配列のポインタを返す方法や、std::array
やstd::vector
を使った方法があります。
それぞれの方法について詳しく解説します。
配列のポインタを返す
配列のポインタを関数から返す方法は、動的にメモリを確保する必要があります。
以下にその例を示します。
#include <iostream>
// 配列のポインタを返す関数
int* createArray(int size) {
int* array = new int[size]; // 動的にメモリを確保
for (int i = 0; i < size; ++i) {
array[i] = i + 1; // 配列に値を設定
}
return array;
}
int main() {
int size = 5;
int* numbers = createArray(size);
for (int i = 0; i < size; ++i) {
std::cout << numbers[i] << " ";
}
std::cout << std::endl;
delete[] numbers; // メモリを解放
return 0;
}
1 2 3 4 5
この方法では、動的にメモリを確保するため、使用後に必ずdelete[]
でメモリを解放する必要があります。
std::arrayを返す
std::array
を関数から返す方法は、配列のサイズが固定されている場合に適しています。
#include <iostream>
#include <array>
// std::arrayを返す関数
std::array<int, 5> createArray() {
std::array<int, 5> array = {1, 2, 3, 4, 5};
return array;
}
int main() {
std::array<int, 5> numbers = createArray();
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
1 2 3 4 5
この方法では、std::array
のサイズが固定されているため、サイズ情報を別途管理する必要がありません。
std::vectorを返す
std::vector
を関数から返す方法は、可変長の配列を扱う場合に適しています。
#include <iostream>
#include <vector>
// std::vectorを返す関数
std::vector<int> createVector(int size) {
std::vector<int> vec(size);
for (int i = 0; i < size; ++i) {
vec[i] = i + 1; // ベクターに値を設定
}
return vec;
}
int main() {
int size = 5;
std::vector<int> numbers = createVector(size);
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
1 2 3 4 5
この方法では、std::vector
のサイズを動的に変更できるため、柔軟な配列操作が可能です。
また、std::vector
は自動的にメモリ管理を行うため、メモリリークの心配がありません。
応用例
配列を関数に渡す基本的な方法を理解したら、次は応用的な使い方を学びましょう。
ここでは、多次元配列や部分配列の渡し方、配列を使ったアルゴリズムの実装例を紹介します。
多次元配列を関数に渡す
多次元配列の定義と渡し方
多次元配列を関数に渡す場合、配列の次元数と各次元のサイズを指定する必要があります。
以下にその例を示します。
#include <iostream>
// 多次元配列を受け取る関数
void printMatrix(int matrix[2][3]) {
for (int i = 0; i < 2; ++i) {
for (int j = 0; j < 3; ++j) {
std::cout << matrix[i][j] << " ";
}
std::cout << std::endl;
}
}
int main() {
int matrix[2][3] = {{1, 2, 3}, {4, 5, 6}};
printMatrix(matrix); // 多次元配列を渡す
return 0;
}
1 2 3
4 5 6
この方法では、配列の次元数と各次元のサイズを関数の引数で指定します。
多次元配列のポインタを使う方法
多次元配列をポインタで渡す場合、ポインタの配列を使うことができます。
#include <iostream>
// 多次元配列をポインタで受け取る関数
void printMatrix(int* matrix, int rows, int cols) {
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
std::cout << *(matrix + i * cols + j) << " ";
}
std::cout << std::endl;
}
}
int main() {
int matrix[2][3] = {{1, 2, 3}, {4, 5, 6}};
printMatrix(&matrix[0][0], 2, 3); // ポインタで渡す
return 0;
}
1 2 3
4 5 6
この方法では、配列の要素をポインタ演算でアクセスします。
配列の一部を関数に渡す
部分配列の渡し方
配列の一部を関数に渡す場合、配列の開始位置と長さを指定します。
#include <iostream>
// 部分配列を受け取る関数
void printSubArray(int* array, int start, int length) {
for (int i = 0; i < length; ++i) {
std::cout << array[start + i] << " ";
}
std::cout << std::endl;
}
int main() {
int numbers[] = {1, 2, 3, 4, 5, 6};
printSubArray(numbers, 2, 3); // 部分配列を渡す
return 0;
}
3 4 5
この方法では、配列の開始位置と長さを指定して部分配列を渡します。
範囲を指定する方法
C++20以降では、std::span
を使って範囲を指定することができます。
#include <iostream>
#include <span>
// std::spanを使って部分配列を受け取る関数
void printSpan(std::span<int> sp) {
for (int num : sp) {
std::cout << num << " ";
}
std::cout << std::endl;
}
int main() {
int numbers[] = {1, 2, 3, 4, 5, 6};
printSpan(std::span<int>(numbers).subspan(2, 3)); // 範囲を指定して渡す
return 0;
}
3 4 5
std::span
を使うことで、配列の一部を簡潔に渡すことができます。
配列を使ったアルゴリズムの実装
ソートアルゴリズムの実装例
配列を使ったソートアルゴリズムの例として、バブルソートを実装します。
#include <iostream>
// バブルソートを実装する関数
void bubbleSort(int* array, int size) {
for (int i = 0; i < size - 1; ++i) {
for (int j = 0; j < size - i - 1; ++j) {
if (array[j] > array[j + 1]) {
std::swap(array[j], array[j + 1]);
}
}
}
}
int main() {
int numbers[] = {5, 3, 2, 4, 1};
int size = sizeof(numbers) / sizeof(numbers[0]);
bubbleSort(numbers, size);
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
1 2 3 4 5
バブルソートは、隣接する要素を比較して並べ替えるシンプルなソートアルゴリズムです。
探索アルゴリズムの実装例
配列を使った探索アルゴリズムの例として、線形探索を実装します。
#include <iostream>
// 線形探索を実装する関数
int linearSearch(int* array, int size, int target) {
for (int i = 0; i < size; ++i) {
if (array[i] == target) {
return i; // 見つかった場合のインデックスを返す
}
}
return -1; // 見つからなかった場合
}
int main() {
int numbers[] = {5, 3, 2, 4, 1};
int size = sizeof(numbers) / sizeof(numbers[0]);
int target = 4;
int index = linearSearch(numbers, size, target);
if (index != -1) {
std::cout << "Found at index: " << index << std::endl;
} else {
std::cout << "Not found" << std::endl;
}
return 0;
}
Found at index: 3
線形探索は、配列の要素を順番にチェックして目的の要素を探すシンプルな探索アルゴリズムです。
よくある質問
まとめ
この記事では、C++における配列を関数に渡す方法や返す方法、さらに応用的な使い方について詳しく解説しました。
配列のポインタや参照、std::array
、std::vector
を用いたさまざまな手法を理解することで、効率的なプログラム設計が可能になります。
これらの知識を活用し、実際のプログラムで配列を効果的に扱ってみてください。