So my question is, why does the standard let me have a class without a destructor if I allocate it on free-store?
Because that's not how standard features work.
The = delete
syntax you're talking about was invented to solve a number of problems. One of them was very specific: making types that were move-only or immobile, for which the compiler would issue a compile-time error if you attempted to call a copy (or move) constructor/assignment operator.
But the syntax has other purposes when applied generally. By =delete
ing a function, you can prevent people from calling specific overloads of a function, mainly to stop certain kinds of problematic implicit conversions. If you don't call a function with a specific type, you get a compile-time error for calling a delete
d overload. Therefore, =delete
is allowed to be applied to any function.
And the destructor of a class qualifies as "any function".
The designed intent of the feature was not to make types which would be non-destructible. That's simply an outgrowth of permitting =delete
on any function. It's not design or intent; it simply is.
While there isn't much use to applying =delete
to a destructor, there also isn't much use in having the specification to explicitly forbid its use on a destructor. And there certainly isn't much use in making =delete
behave differently when applied to a destructor.