1. ホーム
  2. c++

[解決済み] C++で関数から配列へのポインタを返す正しい方法

2022-03-07 16:40:03

質問

私はC++のかなり新しいユーザーで、ポインターを避けてきました。ネットで読んだところでは、配列を返すことはできませんが、ポインタを返すことはできるようです。私はそれをテストするために小さなコードを作成し、これが正常な/正しい方法であるかどうか疑問に思っていました。

#include <iostream>
using namespace std;

int* test (int in[5]) {
    int* out = in;
    return out;
}

int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    int* pArr = test(arr);
    for (int i = 0; i < 5; i++) cout<<pArr[i]<<endl;
    cout<<endl;
    return 0;
}


編集 : これはダメみたいですね。どう書き直せばいいのでしょうか?

int* test (int a[5], int b[5]) {
    int c[5];
    for (int i = 0; i < 5; i++) c[i] = a[i]+b[i];
    int* out = c;
    return out;
}

解決方法は?

あなたのコードはそのままでは正しいのですが、実際のシナリオでどのように使用できるのか、または使用する必要があるのか、理解するのに苦労しています。とはいえ、関数からポインタを返す際には、いくつかの注意点がありますので、ご注意ください。

  • という構文で配列を作成した場合 int arr[5]; スタック上に確保され、その関数にローカルになります。
  • C++ではこの配列へのポインタを返すことができますが、それは 未定義の動作 このポインタが指すメモリをローカルスコープ外で使用すること。読む 実世界に例えたこの素晴らしい回答 を使えば、私が説明するよりもずっと明確に理解できるはずです。
  • 配列のメモリがパージされていないことが保証できれば、スコープ外でも配列を使用することができます。あなたの場合、これは arr から test() .
  • メモリリークを気にせず、動的に確保された配列へのポインタを渡したい場合は、以下の記事を参照してください。 std::unique_ptr / std::shared_ptr<> .

編集 - 行列の乗算のユースケースに答えるために

2つのオプションがあります。素朴な方法としては std::unique_ptr / std::shared_ptr<> . モダンC++のやり方は Matrix クラスをオーバーロードし operator * を使用しなければならず、絶対に新しい rvalue references は、乗算の結果をコピーして関数から取り出すのを避けたい場合です。さらに copy constructor , operator =destructor が必要です。 move constructormove assignment operator . の質問と答えに目を通してください。 この検索 をクリックすると、その実現方法についてより深く知ることができます。

編集2 - 付加的な質問に対する回答

int* test (int a[5], int b[5]) {
    int *c = new int[5];
    for (int i = 0; i < 5; i++) c[i] = a[i]+b[i];
    return c;
}

として使用する場合 int *res = test(a,b); を呼び出すと、コード内のある時点で delete []res で確保したメモリを解放するために test() 関数を使用します。問題は、いつ delete . そこで、その対処法について、解答にまとめました。