C++ Logo

std-proposals

Advanced search

[std-proposals] promote T[] and deprecate delete[]

From: Henning Meyer <hmeyer.eu_at_[hidden]>
Date: Tue, 1 Jul 2025 17:26:02 +0200
I think there was an (unavoidable) missed opportunity in C++98 when
new[] and delete[] were introduced.

What we have currently is unchanged since 1998 and very C:

new std::string[8] returns an object of type std::string*. It is
indistinguishable in its type from the result of new std::string.

When you free it, you must remember that it was allocated via new[] and
pass it into delete[] instead of delete.
Calling delete instead of delete[] is undefined behavior and may lead to
crashes in practice not just memory leaks.

Instead, we could have the following:

new T[n] returns an object of type T[],

we can declare variables of type T[], they have a representation
identical to T*

objects of type T[] decay to T* similar to array decay,

delete p has the behavior of delete[] when p is of type T[].

This would represent the difference in the type system and not just in
the logic within functions.


I think the state of T[] is very odd in the current language:

variables cannot be declared:

int p[]; // will not compile

struct members can be declared, but this is C (flexible array members)
and not allowed in strict C++

struct S {

int p[];

};

There are headers written in C that use use this syntax, and these won't
change to not break existing code.

Function parameters can be declared, but is no different from declaring
a pointer

void fun(int p[]); is the same as void fun(int* p);

As far as I can tell, T[] in C++ is mostly used in specializations of
templates like std::unique_ptr<T[]> which is essentially syntactic sugar
over std::unique_ptr<T,array_deleter<T>>, as an array without bound T[]
cannot be meaningfully used in the current language.

I think the C++ language rules can be amended to allow T[] to represent
T* allocated by new[] and backwards compatibility with C headers can
preserved by disallowing this construct within extern "C" constructs.

Of course, it is easy to imagine generic C++ code that breaks when the
expression new[] returns a type that decays to T* instead of T*.
Whether that is relevant in practice can only be determined by
implementing the proposed changes in a compiler.

I just thought I ask whether I am the only one who thinks this might be
a good idea before (asking for help) implementing this in a branch of
GCC or LLVM.

Regards,
Henning

Received on 2025-07-01 15:26:06