Are 'new' and 'delete' getting deprecated in C++?
I stumbled upon a quiz that involved array declaration with different sizes. The first thing that came to my mind is that I would need to use dynamic allocation with the new
command, like this:
while(T--) {
int N;
cin >> N;
int *array = new int[N];
// Do something with 'array'
delete[] array;
}
However, I saw that one of the solutions allowed the following case:
while(T--) {
int N;
cin >> N;
int array[N];
// Do something with 'array'
}
After a bit of research I read that g++ allows this, but it kept me thinking, in which cases is it then necessary to use dynamic allocation? Or is it that the compiler translates this as dynamic allocation?
The delete function is included. Note, however, that the question in here is not about memory leaks.
Neither snippet you show is idiomatic, modern C++ code.
new
and delete
(and new[]
and delete[]
) are not deprecated in C++ and never will be. They are still the way to instantiate dynamically allocated objects. However, as you have to always match a new
with a delete
(and a new[]
with a delete[]
), they are best kept within (library) classes that ensure this for you. See Why should C++ programmers minimize use of 'new'?.
Your first snippet uses a "naked" new[]
and then never delete[]
s the created array. That's a problem. std::vector
does everything you need here just fine. It will use some form of new
behind the scenes (I won't dive into implementation details), but for all you have to care, it's a dynamic array but better and safer.
Your second snippet uses "variable length arrays" (VLAs), a C feature that some compilers also allow in C++ as an extension. Unlike new
, VLAs are essentially allocated on the stack (a very limited resource). But more importantly, they are not a standard C++ feature and should be avoided because they are not portable. They certainly do not replace dynamic (i.e. heap) allocation.
Well, for starters, new
/delete
are not getting deprecated.
In your specific case, they're not the only solution, though. What you pick depends on what got hidden under your "do something with array" comment.
Your 2nd example uses a non-standard VLA extension which tries to fit the array on the stack. This has certain limitations - namely limited size and the inability to use this memory after the array goes out of scope. You can't move it out, it will "disappear" after the stack unwinds.
So if your only goal is to do a local computation and then throw the data away, it might actually work fine. However, a more robust approach would be to allocate the memory dynamically, preferrably with std::vector
. That way you get the ability to create space for exactly as many elements as you need basing on a runtime value (which is what we're going for all along), but it will also clean itself up nicely, and you can move it out of this scope if you want to keep the memory in use for later.
Circling back to the beginning, vector
will probably use new
a few layers deeper, but you shouldn't be concerned with that, as the interface it presents is much superior. In that sense, using new
and delete
can be considered discouraged.
Your second examples uses variable length arrays (VLAs), which are actually a C99 (not C++!) feature, but nonetheless supported by g++.
See also this answer.
Note that variable length arrays are different from new
/delete
and do not "deprecate" them in any way.
Be also aware that VLAs are not ISO C++.
Modern C++ provides easier ways to work with dynamic allocations. Smart pointers can take care about the cleanup after exceptions (that may happen anywhere if allowed) and early returns, as soon as the referenced data structures go out of scope, so may make sense to use these instead:
int size=100;
// This construct requires the matching delete statement.
auto buffer_old = new int[size];
// These versions do not require `delete`:
std::unique_ptr<int[]> buffer_new (new int[size]);
std::shared_ptr<int[]> buffer_new (new int[size]);
std::vector<int> buffer_new (size); int* raw_access = buffer_new.data();
From C++ 14 you can also write
auto buffer_new = std::make_unique<int[]>(size);
this looks even nicer and would prevent memory leak if the allocation fails. From C++ 20 you should be able to do as much as
auto a = std::make_shared<int[]>(size);
this for me still does not compile at the time of writing with gcc 7.4.0. In these two examples we also use auto
instead of type declaration on the left. In all cases, use array as usual:
buffer_old[0] = buffer_new[0] = 17;
Memory leaks from new
and crashes from doubled delete
is something C++ has been bashed for many years, being the "central point" of argumentation for switching into other languages. Maybe better to avoid.
new and delete are not getting deprecated.
The objects created by new operator can be passed by reference. The objects can be deleted using delete.
new and delete are the foundational aspects of the language. Persistence of an object can be managed using new and delete. These are definitely not going to be deprecated.
The statement - int array[N] is a way of defining an array. The array can be used within the scope of the enclosing code block. It cannot be passed like how an object is passed to another function.