This question is very interesting. It is true that the wording about dynamic storage duration and new
expressions does not exclude the placement-new.
The ambiguity in the formulation is caused by the great variety of cases that need to be covered:
int main()
{
struct Simple { int i; } s { 42 };
new (&s.i) int { 43 }; // the lifecyle of the newly created object
// will auto, since Simple will be destroyed when
// going out of scope
struct Complex { char s[256]; } c;
Simple *p = new (&c.s) Simple; // the lifecycle of the newly created object
// is dynamic. You'll need to delete it in time.
// because compiler doesn't know about its true nature
// and memory will be lost when going out of scope
}
The standard is fortunately precise enough, so that if you provide the right code (i.e. no UB), every compiler will produce the same result.
In fact, dynamic creation of an object (placement new) does not necessarily imply that the object lifecycle is independent of the scope in which the object is created. But it is up to you to make sure that the object will be destroyed in due time, and therefore it is considered as dynamic storage duration.
The key here is the allocation. Only memory allocation can make an object duration truely independent of the scope in which it was created. This is expressed in the standard, but maybe not as clearly as it could have be. Let's start with the full clause in basic.stc/2:
Static, thread, and automatic storage durations are associated with
objects introduced by declarations and implicitly created by the
implementation. The dynamic storage duration is associated with
objects created by a new-expression.
I'd understand here that the last sentence does only apply if the object is not already covered by the first sentence. But this is a personal interpretation for the moment. So the only thing for sure is that in case of overlap, extra care is needed.
So let's look more closely at Dynamic storage duration [ basic.stc.dynamic ]/1
Objects can be created dynamically during program execution (...). A C++ implementation provides access to, and management of,
dynamic storage via the global allocation functions operator new and
operator new[] and the global deallocation functions operator delete
and operator delete[]. [ Note: The non-allocating forms described in
21.6.2.3 do not perform allocation or deallocation. — end note ]
The second sentence makes clear that dynamic storage means allocation. Then comes the interesting note, which refers to exactly the chapter [new.delete.placement]/1:
These functions are reserved; a C++ program may not define functions
that displace the versions in the C++ standard library. The
provisions of 6.7.4 do not apply to these reserved placement forms of
operator new and operator delete.
The section 6.7.4 is the section basic.stc.dynamic. This means that the special allocation used for placement-new does not create dynamic storage.
THe fact that dynamic storage and dynamic storage duration are not one and the same thing makes the whole stuff difficult to express:
- dynamic storage duration means that you have to take care for the object lifecycle and delete when necessary
- dynamic storage means that there are no constraints to the storage duration.
- creating a dynamic storage duration object elsewhere than in dynamic storage (and especially in an automatic storage location) requires extra care, since you need to make sure it is destroyed while the storage is available. If you just replace an object with an object of the same type in a placement-new, you'll benefit from the code that will destroy the object when leaving the scope. But in any other case, you'll need to take care.
Here an online demo to play with placement-new and destruction, and to see what happens when the enclosing object goes out of scope. It uses a Tracer
class that will highlight better than an int
the different cases (including deletion of the previous object before invoking a placement new).
Conclusion: I think that some ambiguity and circularity can't be avoided in any standard with such a long history and with so many contributors. But in this case, you can see that the matter itself has more facets that you'd have expected in first place.