はじめに
C++やC言語で、関数の中で作成した構造体の情報を、呼び出し元のmain
関数などで利用したい場合があります。そのようなとき、関数から**構造体を指すポインタを返す(returnする)**という方法があります。
しかし、これには大きな落とし穴があります。通常のローカル変数は、関数が終了すると同時にメモリ上から消滅してしまいます。もし、消滅した変数のアドレスを返してしまうと、呼び出し元はその無効なアドレス(ごみデータ)を指すことになり、深刻なバグの原因となります(これを「ダングリングポインタ」と呼びます)。
この問題を解決するのが static
キーワードです。この記事では、static
を使って、関数の中から安全に構造体のポインタを返す方法を解説します。
ポインタを返す関数のサンプルコード
このコードは、createDefaultProduct()
という関数を定義します。この関数は、内部で static
な Product
型の変数を作成し、そのアドレスを戻り値として返します。
完成コード
#include <iostream>
#include <string>
// 「商品」構造体の定義
struct Product {
int id;
std::string name;
};
// --- 1. 関数のプロトタイプ宣言 ---
// 戻り値の型として、Product構造体を指すポインタ(Product*)を指定
Product* createDefaultProduct();
int main() {
// --- 2. ポインタ型の変数で、関数の戻り値を受け取る ---
Product* p_item;
p_item = createDefaultProduct();
// --- 3. 受け取ったポインタ経由でメンバにアクセス ---
std::cout << "デフォルトの商品情報" << std::endl;
std::cout << "ID: " << p_item->id << std::endl;
std::cout << "商品名: " << p_item->name << std::endl;
return 0;
}
// --- 関数の本体(定義) ---
Product* createDefaultProduct() {
// --- 4. staticを付けて、ローカル変数を宣言 ---
static Product defaultItem;
defaultItem.id = 999;
defaultItem.name = "標準品";
// --- 5. 作成した変数のアドレス(&)を返す ---
return &defaultItem;
}
コードの解説
1. Product* createDefaultProduct()
関数の戻り値の型を Product*
と定義しています。これは、「この関数は、Product
型の構造体を指す**ポインタ(アドレス)**を返します」という意味です。
2. p_item = createDefaultProduct();
main
関数側では、Product*
型のポインタ変数 p_item
を用意して、createDefaultProduct
関数が返したアドレス値を受け取っています。
3. static Product defaultItem;
これが、このテクニックの最も重要なポイントです。
- 通常のローカル変数: 関数が終了すると、メモリから消滅します。
static
を付けたローカル変数: プログラムが終了するまで、メモリ上に存在し続けます。関数の外からでも、そのアドレスは有効なままです。
static
を付けずに Product defaultItem;
とした場合、関数が終了した瞬間に defaultItem
は消滅し、返されたアドレスは無効になります。その無効なアドレスにアクセスしようとすると、プログラムは未定義の動作(クラッシュなど)を引き起こします。
4. return &defaultItem;
static
で宣言した変数 defaultItem
のアドレスを、アドレス演算子 &
で取得し、関数の戻り値として返しています。
まとめ
今回は、関数から構造体のポインタを安全に返す方法を解説しました。
- 関数の戻り値の型を、ポインタ型(例:
struct_name*
)として宣言する。 - 関数の中で返す構造体変数は、
static
キーワードを付けて宣言し、関数終了後もメモリに残り続けるようにする。 - 関数の戻り値として、その
static
変数のアドレス(&variable
)を返す。
関数からポインタを返す方法は、動的メモリ確保 (new
) を使う方法もありますが、static
ローカル変数を使うのは、関数が常に同じ単一のインスタンスを返せばよい場合に使える、よりシンプルな手法です。