4

関数を次のように宣言すると、 XCodedeclared as array of references of type float&でエラーが発生します。

void calcCoeff(float sigma, float& ap[], float& bp[], float& an[], float& bn[]);

誰が何が問題なのか教えてもらえますか? 私も試しました

void calcCoeff(float sigma, float &ap[5], float &bp[5], float &an[5], float &bn[5]);

ありがとう...

4

2 に答える 2

6

この問題は、エラー メッセージで説明されているとおりです:float& ap[]参照の配列を宣言します。これは、参照へのポインターと参照への参照が禁止されているのと同様に、C++ では有効な型ではありません。

合法である場合、ポインターの配列を考えることで、それが何を意味するかを考えることができます。参照は、いくつかの点で概念的にポインターに似ています。参照は別のエンティティを参照することを意図しており、参照がランタイム表現を必要とする場合、C++ 実装は通常ポインターを使用します。

したがって、ポインターの配列を関数に渡す場合は、初期化を構築する必要があります。

float a, b, c;
float *arr[] = {&a, &b, &c};    // or in fictional array-of-references syntax: float &arr[] = {a, b, c};

または、既に float の配列があり、それらの要素へのポインターの配列が必要な場合:

float a[3];
float *b[] = {&a[0], &a[1], &a[2]);     // or in fictional array-of-references syntax: float &b[] = {a[0], a[1], a[2]};

おそらく、実際に必要なのは、参照によって配列を関数に渡して、関数が配列に書き込むことができ、変更が呼び出し元に表示されるようにすることです。(または単に配列のコピーを避けたいため)。通常、関数のパラメーターは値で渡され、参照で渡す方法&はそこに固執することであるため、配列型に対して同じことを行いました。これは非常に優れた本能ですが、C++ には、それを台無しにするいくつかの問題があります。

1 つ目は、C++ での宣言の奇妙な構文です。「スパイラルルール」または「宣言は使用を模倣する」については他の場所で読むことができますが、それが&変数名またはfloat. float &arr[]参照の配列です。アンパサンドを変数の近くに置くには、いくつかの括弧が必要ですfloat (&arr)[]。配列への参照を宣言します。

次に、残念なことに、C++ は、配列とポインターをほとんど交換可能にすることを目的とした C からいくつかの奇妙な動作を継承しています。あなたの場合に関連する動作は、配列パラメーターを取る関数を宣言した場合です。

void foo(int arr[], int size);

言語は、型がポインターになるように「調整」されていると具体的に述べています。結果は次と同じです。

void foo(int *arr, int size);

これが意味することは、配列は値型のように振る舞わないということです。配列を「値で」渡そうとしても、配列の変更可能なコピーが関数に渡されません。代わりに、関数は効果的に配列を「参照によって」受け取ります。

2 番目の結果は、配列パラメータが完全な配列型を持つ必要がないことです。つまり、配列型は調整され、サイズはとにかく使用されないため、配列サイズを省略できます。これは、サイズを指定しない「配列パラメーター」を単純に配列への参照に変換する場合、&. float (&arr)[10].


私の意見では、生の配列をパラメーターとして使用することは非常に望ましくありません。まず、型情報を破棄するため:

void foo(int arr[10]) { // same as void foo(int *arr)
    int x = arr[9];
}

int bar[3];
foo(bar); // no compile error! the special array rules discarded the size of the array

また、生の配列は他の組み込み型と一貫性がないため、すべて値のセマンティクスがあります。これらの理由から、生の配列は避けるべきです。代わりにstd::array、組み込み配列のすべての「特別な」ルールを回避するため、組み込み配列のように動作する which を使用できます。

void foo(std::array<int, 10> arr); // Takes arr by value, modifications will not be visible externally

std::array<int, 3> bar;
foo(bar); // compile error

動的なサイズの配列が必要な場合は、std::vector代わりに使用できます。

于 2013-01-14T17:16:07.023 に答える
2

次のように変更します。

void calcCoeff(float sigma, float ap[], float bp[], float an[],
               float bn[]);

値を問題なく変更できます。関数の引数の[]表記はポインタに相当します。したがって、これと同じです:

void calcCoeff(float sigma, float* ap, float* bp, float* an,
               float* bn);

つまり、どちらの場合も、コピーではなくデータへのポインターを取得します。[]構文は単なる文体上の決定です。float a[]は と同じことを意味しますがfloat* a[]構文は関数の呼び出し元にとって、単一の変数ではなく配列で機能するというヒントです。

于 2013-01-14T15:53:05.100 に答える