Date: Tue, 1 Jul 2025 15:57:15 -0400
On Tue, Jul 1, 2025 at 1:14 PM Oliver Hunt via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> I agree with Brian that a change of this magnitude would need significantly more justification than “make delete easier”, but more over I am unsure how an unkinded delete would work. It’s necessary to know if you’re deleting an array vs a single allocation for myriad reasons.
The core idea the OP is proposing is for `T[]` to become a real type,
distinct from `T*`. As such, if you create an array, you get a `T[]`
type back. You can turn it into a `T*`, but you cannot delete the
`T*`, only the `T[]` that you'd have to cast it back to. So `delete`
would have all of the information it needs to know when it's deleting
an array vs. an allocation.
>
> > On Jul 1, 2025, at 8:26 AM, Henning Meyer via Std-Proposals <std-proposals_at_[hidden]> wrote:
> >
> > 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
> >
> > --
> > Std-Proposals mailing list
> > Std-Proposals_at_[hidden]
> > https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
<std-proposals_at_[hidden]> wrote:
>
> I agree with Brian that a change of this magnitude would need significantly more justification than “make delete easier”, but more over I am unsure how an unkinded delete would work. It’s necessary to know if you’re deleting an array vs a single allocation for myriad reasons.
The core idea the OP is proposing is for `T[]` to become a real type,
distinct from `T*`. As such, if you create an array, you get a `T[]`
type back. You can turn it into a `T*`, but you cannot delete the
`T*`, only the `T[]` that you'd have to cast it back to. So `delete`
would have all of the information it needs to know when it's deleting
an array vs. an allocation.
>
> > On Jul 1, 2025, at 8:26 AM, Henning Meyer via Std-Proposals <std-proposals_at_[hidden]> wrote:
> >
> > 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
> >
> > --
> > Std-Proposals mailing list
> > Std-Proposals_at_[hidden]
> > https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
Received on 2025-07-01 19:57:29