1

参考文献 私の最後の投稿と、値ではなく参照で配列を渡すことに関するその投稿へのセリビツェのコメントに、配列を値ではなく参照で渡すときに、コンパイラーが引数を推測できるのに、値で渡すとそれができないのはなぜですか?

template<class T,int row, int col>
void invert(T (&a)[row][col]) //NOTE AMPERSAND

上記の宣言を使用してメインで呼び出すことができます:

int main(int argc, char* argv[])
{
invert(a);//HERE ARGUMETS ARE AUTOMATICALLY DEDUCED
}

しかし、アンパサンドがなければ、次のように呼び出す必要があります。

 int main(int argc, char* argv[])
    {
    invert<int,3,4>(a);
    }

@Paulだから、fncを宣言するときに明確にするために:

void f(int a[]);//I'm passing a pointer

しかし、私が宣言しているとき:

void f(int &a[]);//I'm passing a ref?

私は今これを正しく理解していますか?

4

3 に答える 3

3

これは、配列を「値で」渡すと、ポインターに減衰するためです。つまり、実際には、サイズ情報なしで最初の要素へのポインターを渡しています。

次のような署名がある場合:

 void foo(int arr[10]);

値 10 は完全に無視され、任意のサイズの int の配列を渡すことができます。とまったく同じです。

 void foo(int arr[]);

また

void foo(int* arr);

ご覧のとおり、サイズ情報は保持されないため、配列のサイズを推測するために使用することはできません。

2 次元配列では、最初の次元が減衰します。たとえば、20 個の整数の 10 個の配列の配列 ( int arr[10][20]) は、20 個の整数の配列へのポインター ( int (*arr)[20]) などに減衰するため、値 10 は推定できませんが、2 番目の次元のサイズ (20) は保持され、推定できます。

template<class T,int row, int col>
void foo(T (&a)[row][col]) { }

template <class T, int col>
void bar(T arr[][col]) {}

int main()
{
    int a[10][20];
    foo(a);
    bar(a);
}

参照によって何かを渡すと、型が保持され、配列が減衰せず、すべてのサイズ情報が引き続き使用可能になります。

于 2010-04-02T11:14:28.410 に答える
1

配列を値で渡すことはできず、ポインターでのみ渡すことができます (配列を関数に渡すと、自動的にポインターに変換されます)。

「引数を推測する」の意味がよくわかりません。配列の合計サイズを意味しますか? はいの場合、ポインターで渡すと、ポインターはそのような情報を保持しないため、失われます。

とにかく、単純な古い C 配列ではなく、使用することを強くお勧めします。std::vector頭痛がずっと少ない!これらはデフォルトで値渡しされます (ご想像のとおり)。必要に応じて、参照およびポインターによって簡単に渡すことができ、配列サイズなどの情報が失われることはありません。また、バッファーのオーバーフローやアンダーフローから保護し、要素を追加すると自動的に大きくなります。

于 2010-04-02T10:48:21.723 に答える
1
void f(int &a[]); // I'm passing a ref?

いいえ、ここでは型システムに存在しない参照の配列を渡そうとしています。次のように書きたくなるかもしれません。

void f(int (&a)[]);

ただし、境界が不明な配列への参照は、関数パラメーターとして許可されていません。


関数パラメーターを n 次元の配列として宣言すると、コンパイラによって n-1 次元の配列へのポインターとして書き換えられます。次の署名は同等です。

void fun(int x[][10]);
void fun(int x[2][10]);
void fun(int x[99][10]);
void fun(int (*x)[10]);

最初の次元の境界は無視されるため、テンプレート メカニズムでは推測できません。

できることは、2D 配列全体へのポインターを渡すことです。

template <class T, int row, int col>
void invert(T (*a)[row][col])
{
    std::cout << row << " x " << col << std::endl;
    T first_entry = (*a)[0][0];
}

int main(int argc, char* argv[])
{
    int a[10][20];
    invert(&a);
}

これは期待どおりに機能しますが、ご覧のとおり、構文は両側で少し不器用です。

于 2010-04-02T11:14:13.450 に答える