1. 導入:なぜ「自己参照構造体」が必要なのか?
C++でプログラミングをしていると、「データの個数が実行するまで分からない」「データを順番に繋げて管理したい」という場面に遭遇します。配列は便利ですが、サイズが固定という弱点があります。この課題を解決し、柔軟なデータ管理を実現するために不可欠なのが「自己参照構造体」です。これを使うことで、連結リスト(Linked List)のような動的なデータ構造を作れるようになります。
2. 基礎知識:自己参照構造体とは?
自己参照構造体とは、自分自身の型のポインタをメンバとして持つ構造体のことです。
なぜ「ポインタ」を使う必要があるのでしょうか? それは、構造体の中に自分自身の「実体」を含めてしまうと、サイズが無限大になってしまい、コンパイルエラーになるからです。ポインタであればサイズが固定(64bit環境なら8バイトなど)であるため、自分自身を指し示すことが可能になります。
3. 実装・解決策
基本的には、構造体の中に「次の要素を指すポインタ」を定義します。このポインタを辿ることで、バラバラにメモリ上に配置されたデータを鎖のように繋いでいくことができます。
4. サンプルプログラム
以下のコードは、整数値を保持し、次のノードへ繋いでいくシンプルなリストの例です。
include
// 自己参照構造体の定義
struct Node {
int data; // 保持するデータ
Node next; // 次のノードを指すポインタ
};
int main() {
// 3つのノードを作成
Node n1 = {10, nullptr};
Node n2 = {20, nullptr};
Node n3 = {30, nullptr};
// ノード同士を連結する
n1.next = &n2;
n2.next = &n3;
// リストを辿って表示する
Node current = &n1;
while (current != nullptr) {
std::cout << "データ: " << current->data << std::endl;
// 次のノードへ移動
current = current->next;
}
return 0;
}
5. 応用・注意点
現場でこの仕組みを使う際に注意すべきポイントが2つあります。
・メモリリークに注意
上記の例では静的な変数を使っていますが、実際には new演算子 を使って動的にメモリを確保することがほとんどです。確保したメモリは必ず delete演算子 で解放しないと、メモリリークの原因となります。
・nullptrの扱い
リストの最後を示すために「nullptr」を代入するのを忘れないでください。これを怠ると、リストを辿る処理がメモリの不正な領域まで読みに行ってしまい、プログラムがクラッシュする危険性があります。
まずはこの「ポインタで繋ぐ」感覚を掴むことで、将来的にstd::listやstd::vectorの内部構造を理解する強力な足掛かりになります。ぜひ実際にコードを書いて試してみてください。

コメント