0

いくつかの質問が発生したとき、(配列の動的割り当てを避けるために) 非型パラメーターを使用するテンプレート関数に取り組んでいました。私の最初の質問は、コンパイル時の変数の割り当てに関するものです。これは、テンプレート関数への次の呼び出しの試行から発生しました。

template<int n>
int *getDegrees(int A[][n]) {
  //return degrees
}

int main(int argc, char **argv) {
  int n = 10;
  int A[n][n];
  int *degs = getDegrees<n>(A);
}

ここでは、2 つのエラーがあります。1 つ目は、コンパイラが への呼び出しを解決できないことgetDegrees(A)です。

main.cc:27: error: no matching function for call to ‘getDegrees(int [(((long unsigned int)(((long int)n) + -0x00000000000000001)) + 1)][(((long unsigned int)(((long int)n) + -0x00000000000000001)) + 1)])’

n次に、定数式ではないため、テンプレート呼び出しで使用できません。単にn定数にするだけで問題が解決します

const int n = 10;

しかし、もし私がするなら

int m = 10;
const int n = m; 

同じエラーが発生します。2 番目の代入はコンパイラによって許可される場合がありますが、そうするのは悪い形式と見なされますか? さらに、n定数にすることで関数呼び出しの解決に違いが生じるのはなぜですか?

私の他の質問は vlas に関するものです: メモリはスタックまたはヒープに割り当てられていますか (そしてこれはコンパイラに依存していますか)? ベクトル (または同様のコンテナー) を優先して回避する必要がありますか?

洞察に感謝します!

4

1 に答える 1

5

あなたの質問から得られるものは何でも答えようとします。
関数プロトタイプを変更して、参照によって配列を受け取ることができます。

template<size_t n> // see the type
int *getDegrees(int (&A)[n][n]) {  // see the signature
  // ...
}

上記のコードでは、配列の次元が同じであるという事実を利用しています。
ただし、一般的には次のようにする必要があります。

template<size_t n1, size_t n2> // see the type
int *getDegrees(int (&A)[n1][n2]) {  // see the signature
  // ...
}

サイズが大きすぎる場合、コンパイラによってエラーが発行されて通知されます。例 (g++ から):

エラー: 配列 'A' のサイズが大きすぎます

ここで、定数整数の割り当ての違いに関する他の質問に進みます。
C++ では、配列サイズはコンパイル時定数である必要があり、

const int n = 10;

その要件を満たします。コンパイラはそれを認識できるため、10 は に割り当てられるリテラル番号nです。

の場合には、

int m = 10;
const int n = m;

コンパイラは、 のソースがコンパイル時定数自体でnないことを検出します。したがって、コードの形式が正しくありません。

于 2013-07-15T18:40:02.120 に答える