1

次のように私は、一次元配列のためにnew演算子を書き込むことができます。オペレータnewが非定型サイズの多次元配列を構築できないのはなぜですか?

int n{3}; 
new int[n]; 

それは少なくともsizeof(int) * nバイトを割り当てます。しかし、2次元配列を作成する場合は、最初の次元だけが非定数になることがあります。

int n{3}; 
new int[n][3]; //ok 
new int[n][n]; //error; 

なぜこのような制限が行われるのですか?決定するのが難しいですか、それは少なくともsizeof(int) * n * nバイトを割り当てることですか?

+0

VLAに自動ストレージを設定することはできません。なぜ、動的記憶域に使用できるのですか? – StoryTeller

+0

StoryTellerですが、1次元配列の場合はそれが機能しますが、なぜ次元配列が許されないのですか? – user3514538

+1

あなたはVLAを持っていません。つまり、VLAのint(*)[n] 'へのポインタを持つことはできません。それは、そのような式が返す必要があるものです。 – StoryTeller

答えて

1

C++型システムには、実行時にバインドされた配列は含まれていません。これは、テンプレートと過負荷解決に影響を与えることを考慮すると、非常に複雑なことです。提案はされているが、誰も標準化のために受け入れられるまで進んでいない。

したがってT[n]は有効なタイプではありません。ただし、特別なケースがあるので、new-expressionで使用することができます。 new - 式のいずれかであり得る:

XTタイプであり、 nは定数式ではないタイプ
  • new T[n]、ある
      new X
    • 、。

    T[n]はタイプではありませんが、newの表現で許可したいので、両方のケースが必要であることに注意してください。

    2番目の点はもう少し説明が必要です。実際にはC++の中置表記法を使用していますので、Tが配列または関数型の場合、[n]は別の場所にあります。たとえばnew int[n][3]はOKです。これはtypedef int T[3]; new T[n]と同じです。しかしnew int[3][n]ではありません。

    new int[3][n]を許可した場合、返品の種類はどのようになりますか? int (*)[n]は、前述のようにC++型システムの一部ではありません。

  • 3

    この場合の問題は、どのくらいのメモリを割り当てるかを決定することではありません。その部分は実際には簡単です。

    問題は、後でこのような配列へのアクセスを整理することです。もしあなたが知っていれば、C++の多次元配列は、インデックスの再マッピングを伴う線形(1次元)配列として実装されています。あなたは

    int a[N][M]; 
    

    を宣言するときにたとえば、コンパイラが実際にボンネットの下にint [N * M]配列を作成します。後でa[i][j]としてアクセスすると、後者は暗黙のうちにa[i * M + j]へのアクセスに変換されます。 C++コンパイラは、コンパイル時にMの値を知っていることを主張しています(一方、Nという値はインデックスの再計算式にはまったく関与しません)。

    これは、配列がポインタに崩壊して多次元配列の最初のサイズが重要でないコンテキストで、2番目、3番目、およびそれ以上のサイズがコンパイル時定数でなければならない理由です。これは、new []に課せられた制限を決定するものです。

    P.S. C言語は、すべてのサイズを実行時の値にすることができる可変長配列をサポートしています。これには、実行時の値MNを上記の例のアレイaと一緒に保存するような追加の努力が必要です。これは最終的にはC++には不適切だと思われていました。

    関連する問題