differences between new char[n] and new (char[n])

后端 未结 3 722
攒了一身酷
攒了一身酷 2021-01-03 20:24

Is there any difference between new char[n] and new (char[n])?

I have the second case in a generated code, g++ (4.8.0) gives me

<         


        
相关标签:
3条回答
  • 2021-01-03 20:53
    • new T[N] makes an array of N elements of type T.

    • new (T[N]) makes a single object of type T[N].

    The effect is the same (and both expressions yield a T * that points to the first element of the array and needs to be deleted with delete[] (cf. 5.3.4/5), but clearly T[N] must be a valid type in the latter case, so N must be a constant expression, while in the former case it is a dynamic argument of the array-new expression.

    0 讨论(0)
  • 2021-01-03 20:57
      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
    +----------------------------------------------------------------+
    |+-----+-----+-----+-----+-----+-----+-----+-----+------+------+ |
    ||     |     |     |     |     |     |     |     |      |      | |
    ||     |     |     |     |     |     |     |     |      |      | |
    ||     |     |     |     |     |     |     |     |      |      | |
    |+-----+-----+-----+-----+-----+-----+-----+-----+------+------+ |
    +----------------------------------------------------------------+
    

    In fact both of them are equal.

     

    Here is the code generated by assembler (just an ignorable difference):

    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)
    

    You must delete both of them by delete [] ...

    0 讨论(0)
  • 2021-01-03 21:03

    The basic issue here is that C++ does not allow an array bound [n] to be used in a type unless n is a constant expression. g++ and some other compilers will sometimes allow it anyway, but it's impossible to get consistent behavior when you start mixing variable-length-arrays and templates.

    The apparent exception int* p = new int[n]; works because here the [n] is syntactically part of the new expression, not part of the type provided to the new, and new does "know how" to create arrays with length determined at runtime.

    // 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;
    }
    

    Semantically, though, after any final [C] is used to convert a type into an array type, the new expression only cares about whether it's dealing with an array or not. All the requirements about type of the expression, whether to use new[] and delete[], and so on say things like "when the allocated type is an array", not "when the array new syntax is used". So in the example above, the initializations of p1, p2, and p3 are all equivalent, and in all cases delete[] is the correct deallocation form.

    The initialization of p4 is valid, but the code for p5 and p6 is not correct C++. g++ would allow them anyway when not using -pedantic, and by analogy I'd expect the initializations for p4, p5, and p6 to also all be equivalent. @MM's disassembly supports that conclusion.

    So yes, it should be a safe improvement to remove the "extra" parentheses from this sort of expression. And the correct deletion is the delete[] type.

    0 讨论(0)
提交回复
热议问题