23

と の間に違いはnew char[n]ありnew (char[n])ますか?

生成されたコードに2番目のケースがあります.g ++(4.8.0)は私に与えます

ISO C++ does not support variable-length array types [-Wvla]

これは、これら2つが同じかどうかを考えさせます。

  1. new char[n]n「タイプのオブジェクトを割り当てる」を意味しますchar
  2. new (char[n])「タイプのオブジェクトを1つ割り当てる」という意味ですかarray of n chars?
  3. 最初の削除は明らかです。
  4. またはで 2 番目を削除する必要がありますdeletedelete[]?
  5. 私が知っておくべき他の違いはありますか?
  6. ソフトウェアの他の部分が 2 番目のケースを想定している場合、かっこを安全に削除して 2 番目のケースを最初のケースに変更してもよいでしょうか?

コードはサードパーティのソフトウェアによって生成されます (そして、ソフトウェアの他の部分で使用されます)。

これは最小限の例です:

int main (void)
{
    int n(10);
    int *arr = new (int[n]); // removing parentheses fixes warning
    *arr = 0; // no "unused variable" warning
    return 0;
}
4

3 に答える 3

10

ここでの基本的な問題は、C++ では、定数式で[n]ない限り、バインドされた配列を型で使用できないことです。ng++ やその他の一部のコンパイラでは、とにかく許可されることがありますが、可変長配列とテンプレートを混在させ始めると、一貫した動作を得ることができなくなります。

int* p = new int[n];ここでは、 はに提供される型の一部ではなく[n]、構文的に式の一部であり、実行時に決定される長さの配列を作成する方法を「知っている」ため、明らかな例外が機能します。newnewnew

// can be "constexpr" in C++11:
const int C = 12;

int main() {
    int* p1 = new int[C];
    int* p2 = new (int[C]);
    typedef int arrtype[C];
    int* p3 = new arrtype;

    int n = 10;
    int* p4 = new int[n];
    // int* p5 = new (int[n]);  // Illegal!
    // typedef int arrtype2[n]; // Illegal!
    // int* p6 = new arrtype2;

    delete[] p1;
    delete[] p2;
    delete[] p3;
    delete[] p4;
}

ただし、意味的には、任意の final[C]を使用して型を配列型に変換した後、新しい式は配列を扱っているかどうかだけを気にします。式の型、 and を使用するかどうかなどに関するすべての要件new[]delete[]、「配列の新しい構文が使用される場合」ではなく、「割り当てられた型が配列である場合」のようなものです。したがって、上記の例ではp1、 、p2、およびの初期化p3はすべて同等であり、すべての場合delete[]で正しい解放形式です。

の初期化p4は有効ですが、 と のコードp5p6正しい C++ ではありません。g++ は、 を使用していない場合でもそれらを許可します。同様に、 、、およびの初期化もすべて同等であると-pedantic予想します。@MM の分解はその結論を支持します。p4p5p6

そうです、この種の式から「余分な」括弧を削除することは安全な改善であるはずです。そして、正しい削除はdelete[]タイプです。

于 2013-05-19T13:24:39.257 に答える
3
  new int [n]
  //Allocates memory for `n` x `sizeof(int)` and returns
  //the pointer which points to the beginning of it. 

 +-----+-----+-----+-----+-----+-----+-----+-----+------+------+
 |     |     |     |     |     |     |     |     |      |      |
 |     |     |     |     |     |     |     |     |      |      |
 |     |     |     |     |     |     |     |     |      |      |
 +-----+-----+-----+-----+-----+-----+-----+-----+------+------+


  new (int [n])
  //Allocate a (int[n]), a square which its item is an array
+----------------------------------------------------------------+
|+-----+-----+-----+-----+-----+-----+-----+-----+------+------+ |
||     |     |     |     |     |     |     |     |      |      | |
||     |     |     |     |     |     |     |     |      |      | |
||     |     |     |     |     |     |     |     |      |      | |
|+-----+-----+-----+-----+-----+-----+-----+-----+------+------+ |
+----------------------------------------------------------------+

実際、両者は等しい。

 

アセンブラによって生成されたコードは次のとおりです (無視できる違いです)。

int n = 10;
int *i = new (int[n]);
int *j = new int[n];

i[1] = 123;
j[1] = 123;

----------------------------------

!    int *i = new (int[n]);
main()+22: mov    0x1c(%esp),%eax
main()+26: sub    $0x1,%eax
main()+29: add    $0x1,%eax
main()+32: shl    $0x2,%eax
main()+35: mov    %eax,(%esp)
main()+38: call   0x401620 <_Znaj> // void* operator new[](unsigned int);
main()+43: mov    %eax,0x18(%esp)
!    int *j = new int[n];
main()+47: mov    0x1c(%esp),%eax
main()+51: shl    $0x2,%eax
main()+54: mov    %eax,(%esp)
main()+57: call   0x401620 <_Znaj> // void* operator new[](unsigned int);
main()+62: mov    %eax,0x14(%esp)
!    
!    i[1] = 123;
main()+66: mov    0x18(%esp),%eax
main()+70: add    $0x4,%eax
main()+73: movl   $0x7b,(%eax)
!    j[1] = 123;
main()+79: mov    0x14(%esp),%eax
main()+83: add    $0x4,%eax
main()+86: movl   $0x7b,(%eax)

あなたdeleteはそれらの両方をdelete [] ...

于 2013-05-19T12:42:28.337 に答える