C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++が配列を返す関数をサポートしない理由を解説

C++では、関数から配列そのものを返すことができません。なぜそうなっているのか、具体的なプログラム例を見ながら解説します。

問題となるサンプルコード

まず、次のプログラムを見てください。ローカル配列のアドレスを返そうとしている例です。

#include <iostream>
using namespace std;

int* Array() {
    int a[100];
    a[0] = 7;
    a[1] = 6;
    a[2] = 4;
    a[3] = 3;
    return a;  // ローカル変数のアドレスを返している
}

int main() {
    int* p = Array();
    cout << p[0] << " " << p[1] << " " << p[2] << " " << p[3];
    return 0;
}

コンパイル時の警告

このプログラムをコンパイルすると、次のような警告が出力されます。

In function 'int* Array()':
warning: address of local variable 'a' returned [-Wreturn-local-addr]
int a[100];

なぜ配列を返せないのか

この警告の原因は、ローカル変数(自動記憶域期間を持つ変数)のアドレスを返している点にあります。

ローカル変数は、関数が呼び出されたときにスタック上に確保され、関数の処理が終了した時点でメモリから解放されます。つまり、関数呼び出しが終わった後は、その配列「a」はメモリ上に存在しなくなるため、返されたポインタは無効なアドレス(ダングリングポインタ)を指すことになります。

仮にコンパイルが通っても、解放済みのメモリ領域にアクセスすることになり、未定義動作(Undefined Behavior)を引き起こします。結果として、正しい値が表示されなかったり、プログラムがクラッシュしたりする可能性があります。

このような危険を避けるため、C++では関数が配列を直接返すことをサポートしていないのです。

代替手段:安全に複数の値を返す方法

配列を返したい場面では、以下のような方法を使うのが一般的です。

1. std::vector を使う

#include <vector>

std::vector<int> Array() {
    return {7, 6, 4, 3};
}

std::vector はヒープ領域にデータを保持するため、関数終了後も有効です。現代のC++では最も推奨される方法です。

2. std::array を使う

#include <array>

std::array<int, 4> Array() {
    return {7, 6, 4, 3};
}

サイズが固定であれば、std::array も値として返せる便利な選択肢です。

3. 動的メモリ確保を使う

int* Array() {
    int* a = new int[4];
    a[0] = 7; a[1] = 6; a[2] = 4; a[3] = 3;
    return a;
}
// 呼び出し側で delete[] による解放が必要

new で確保したメモリは関数終了後も残りますが、呼び出し側で必ず delete[] する必要があり、メモリリークのリスクがあります。

まとめ

C++が配列を返す関数をサポートしないのは、ローカル配列が関数終了とともに破棄され、返されたアドレスが無効になるためです。代わりに std::vector や std::array といったコンテナクラスを活用すれば、安全かつ簡潔に複数のデータを返すことができます。

  1. GCCにおけるC++標準規格のサポート状況と-std=オプションの使い方

    GCCがサポートするC++標準規格GCC(GNU Compiler Collection)は、ISOによって策定・公開された複数のC++標準規格(方言)に対応しています。どの規格に基づいてコンパイルを行うかは、-std= コマンドラインオプションで選択できます。C++98 / C++031998年に制定された最初のC++標準規格です。2003年の改訂により「C++03」と改名され、その後の一部の欠陥報告も反映されています。GCCはこの規格を完全にサポートしています。C++11旧称は「C++0x」。2011年に公開されたC++標準規格で、ラムダ式やauto型推論など数多くの新機能が導入されました

  2. 可変長配列(VLA)がC++標準に採用されない理由と代替手段「std::vector」の使い方

    可変長配列(VLA)とは可変長配列(Variable Length Array、VLA)とは、実行時にサイズが決まる配列のことです。C99では標準機能として採用されましたが、C++の標準規格には含まれていません。本記事では、その理由と、C++で代わりに利用できる方法を解説します。可変長配列がC++標準に採用されない理由スタックは通常、利用できる領域が非常に限られています。そのため、大きなサイズになりうる配列をスタック上に作成しなければならない状況は、プログラムの安定性の観点から好ましくありません。また、コンパイル時にサイズがわかっているのであれば静的配列を使えばよく、逆にサイズが事前にわからな