web-dev-qa-db-ja.com

関数への、または関数からの(ポインタではなく)配列の参照を渡す/返す一般的な規則?

次のような関数に配列の参照を渡すことができます。

_void f(int (&a)[5]);

int x[5];
f(x);     //okay
int y[6];
f(y);     //error - type of y is not `int (&)[5]`.
_

またはさらに良いことに、関数テンプレートを書くことができます:

_template<size_t N>
void f(int (&a)[N]); //N is size of the array!

int x[5];
f(x);     //okay - N becomes 5
int y[6];
f(y);     //okay - N becomes 6
_

今私の質問は、関数から配列の参照を返す方法ですか?

関数から次のタイプの配列を返したい:

_int a[N];
int a[M][N];
int (*a)[N];
int (*a)[M][N];
_

ここで、MおよびNはコンパイル時に既知です!

配列のコンパイル時参照を関数との間でやり取りするための一般的なルールは何ですか? int (*a)[M][N]型の配列の参照を関数に渡すにはどうすればよいですか?

編集:

Adamコメント付き:int (*a)[N]は配列ではなく、配列へのポインタです。

はい。しかし、1つの次元はコンパイル時に既知です。コンパイル時にわかっているこの情報を関数に渡すにはどうすればよいですか?

33
Nawaz

関数から配列への参照を返す場合、宣言は次のようになります。

// an array
int global[10];

// function returning a reference to an array
int (&f())[10] {
   return global;
}

配列への参照を返す関数の宣言は、配列への参照である変数の宣言と同じように見えますが、関数名の後には()が続きます。

int (&variable)[1][2];
int (&functionA())[1][2];
int (&functionB(int param))[1][2];

このような宣言は、typedefを使用することにより、より明確にすることができます。

typedef int array_t[10];

array_t& f() {
   return global;
}

本当に混乱させたい場合は、配列への参照を受け取り、そのような参照を返す関数を宣言できます。

template<int N, int M>
int (&f(int (&param)[M][N]))[M][N] {
   return param;
}

ポインタの配列は同じように機能しますが、*ではなく&を使用する点が異なります。

44
sth

C++ 11の末尾の戻り型構文を使用すると、次のように書くこともできます。

auto foo () -> int (&)[3]
{
    static int some_array[3]; // doesn't have to be declared here
    return some_array; // return a reference to the array.
}
10
Thomas Eding

関数から配列を返すことはできません。

8.3.5/6:

関数は、配列型または関数の戻り値の型を持たないものとします。ただし、戻り値の型がポインターまたはそのようなものへの参照である場合があります。

編集:あなたは構文を気に入るはずです:

int (&bar()) [5] {
  static int x[5];
  return x;
}


int (* & bar()) [6][10] {
    static int x[6][10];
    static int (*y)[6][10] = &x;
    return y;
}
// Note - this returns a reference to a pointer to a 2d array, not exactly what you wanted.
9
Erik

Erikが言及した のように、関数から配列を返すことはできません。構文は非常に複雑ですが、ポインターまたは参照を返すことができます。

// foo returns a pointer to an array 10 of int
int (*foo(float arg1, char arg2))[10] { ... }

// bar returns a reference to an array 10 of int
int (&foo(float arg1, char arg2))[10] { ... }

配列型のtypedefを作成することを強くお勧めします。

// IntArray10 is an alias for "array 10 of int"
typedef int IntArray10[10];

// Equivalent to the preceding definitions
IntArray10 *foo(float arg1, char arg2) { ... }
IntArray10 &bar(float arg1, char arg2) { ... }
3
Adam Rosenfield

Sthによる細かい答えの補足として、配列参照を返す定数メソッドを使用してクラスを宣言する方法を次に示します。

class MyClass
{
public:
    const int (&getIntArray() const)[10];
};
1
Richard Struben

これはC++のタグが付けられているので、C++で配列を返す方法はstd::vectorを返すことであり、C配列を使用したトリックを行わないことをお勧めします(これは、 C++コード)。

他の回答が述べたように、関数からC配列を返すことはできません。

0
Mark B