Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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

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

This makes me think if these two are the same or not.

  1. new char[n] means "allocate n objects of type char.
  2. does new (char[n]) mean "allocate 1 object of type array of n chars"?
  3. deleting the first is clear.
  4. should I delete the second with delete or delete[]?
  5. are there any other differences I should be aware of?
  6. may I safely remove the parentheses and turn the second case into the first, when other parts of the software expect the second?

The code is generated by a third party software (and used by other parts of the software), so I cannot just "use vector instead".

This is minimal example:

int main (void) {     int n(10);     int *arr = new (int[n]); // removing parentheses fixes warning     *arr = 0; // no "unused variable" warning     return 0; } 
like image 675
Adam Trhon Avatar asked May 19 '13 12:05

Adam Trhon


People also ask

What is new char in C++?

You can create an array with zero bounds with the new operator. For example: char * c = new char[0]; In this case, a pointer to a unique object is returned. An object created with operator new() or operator new[]() exists until the operator delete() or operator delete[]() is called to deallocate the object's memory.


1 Answers

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.

like image 94
aschepler Avatar answered Sep 23 '22 07:09

aschepler