C++ の配列へのポインタ
この記事では、C++ で配列へのポインターを使用する方法に関する複数の方法を示します。
C++ で配列へのポインタを使って異なる配列の要素を入れ替える
ポインタは、低水準プログラミングのコア要素の 1つです。C++ はユースケースの一部を参照に置き換えようとしますが、ポインターは、メモリを直接処理するために利用できる組み込みのデータ型にすぎません。C スタイルの配列は基本的に開始要素へのポインタであり、固定サイズのコンパイラがあるため、内部で []
表記のアクセスを自動的に処理することに注意してください。次のサンプルコードでは、異なる整数配列から 2つの要素を交換する関数を実装します。関数プロトタイプは、交換する必要のある要素を示すために 2つの int*
ポインターを使用することに注意してください。ポインタを使用すると、要素のローカルインスタンスを変更するだけでなく、指定された要素のメモリ位置に直接アクセスできます。
#include <iostream>
using std::cout;
using std::endl;
constexpr int SIZE = 4;
void swapArrayElements(int* e1, int* e2) {
int z = *e1;
*e1 = *e2;
*e2 = z;
}
void printArray(int (&arr)[SIZE]) {
for (const auto& item : arr) {
cout << item << ", ";
}
cout << endl;
}
int main() {
int arr1[] = {11, 42, 53, 44};
int arr2[] = {10, 21, 30, 99};
printArray(arr1);
printArray(arr2);
cout << endl;
swapArrayElements(&arr1[0], &arr2[3]);
printArray(arr1);
printArray(arr2);
cout << endl;
return EXIT_SUCCESS;
}
出力:
11, 42, 53, 44,
10, 21, 30, 99,
99, 42, 53, 44,
10, 21, 30, 11,
または、配列ポインタと要素の位置を別々に渡すこともできます。この方法は本質的に以前よりも優れているわけではありませんが、配列へのポインターを利用できるさまざまな言語表記を示すためにここにあります。この場合、スワップする必要のある要素の位置を指定するために 2つの関数引数が追加されます。一方、要素へのアクセスは、いわゆるポインタ演算
を使用して行われます。これは、非常に面倒な表記になる可能性があります。配列へのポインタを整数値でインクリメントすることは、ポインタを要素タイプにインクリメントすることと同じであることに注意してください。これにより、ポインタ値がオブジェクトタイプの sizeof
バイトだけ移動します。
#include <iostream>
using std::cout;
using std::endl;
constexpr int SIZE = 4;
void swapArrayElements(int* arr1, int e1, int* arr2, int e2) {
int z = *(arr1 + e1);
*(arr1 + e1) = *(arr2 + e2);
*(arr2 + e2) = z;
}
void printArray(int (&arr)[SIZE]) {
for (const auto& item : arr) {
cout << item << ", ";
}
cout << endl;
}
int main() {
int arr1[] = {11, 42, 53, 44};
int arr2[] = {10, 21, 30, 99};
printArray(arr1);
printArray(arr2);
cout << endl;
swapArrayElements(arr1, 1, arr2, 2);
printArray(arr1);
printArray(arr2);
cout << endl;
}
出力:
99, 42, 53, 44,
10, 21, 30, 11,
99, 30, 53, 44,
10, 21, 42, 11,
C++ で配列参照を使って 2 次元配列を関数に渡す
2 次元の C スタイルの配列を渡すと、かなり醜くなる可能性があるため、代わりに参照表記を使用することをお勧めします。ただし、次の関数例は、事前定義された長さサイズの配列に適しているため、関数プロトタイプには各次元のサイズ値が含まれます。利点として、これにより、要素の走査に範囲ベースの for
ループを利用できるようになります。
#include <iomanip>
#include <iostream>
using std::cout;
using std::endl;
using std::setw;
constexpr int SIZE = 4;
void MultiplyArrayByTwo(int (&arr)[SIZE][SIZE]) {
for (auto& i : arr) {
for (int& j : i) j *= 2;
}
}
void printArray(int (&arr)[SIZE][SIZE]) {
for (auto& i : arr) {
cout << " [ ";
for (int j : i) {
cout << setw(2) << j << ", ";
}
cout << "]" << endl;
}
}
int main() {
int array_2d[SIZE][SIZE] = {
{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}};
printArray(array_2d);
MultiplyArrayByTwo(array_2d);
cout << endl;
printArray(array_2d);
return EXIT_SUCCESS;
}
出力:
[ 1, 2, 3, 4, ]
[ 5, 6, 7, 8, ]
[ 9, 10, 11, 12, ]
[ 13, 14, 15, 16, ]
[ 2, 4, 6, 8, ]
[ 10, 12, 14, 16, ]
[ 18, 20, 22, 24, ]
[ 26, 28, 30, 32, ]