Current draft standard says (previous standards have similar wording) in [basic.life/1]:
The lifetime of an object or reference is a runtime property of the object or reference. An object is said to have non-vacuous initialization if it is of a class or aggregate type and it or one of its subobjects is initialized by a constructor other than a trivial default constructor. [ Note: Initialization by a trivial copy/move constructor is non-vacuous initialization. — end note ] The lifetime of an object of type T begins when:
(1.1) storage with the proper alignment and size for type T is obtained, and
(1.2) if the object has non-vacuous initialization, its initialization is complete,
See this code:
alignas(int) char obj[sizeof(int)];
Does basic.life/1 mean that here an int
(and several other types, which has the same or less alignment/size requirements as int
) has begun its lifetime?
What does this even mean? If an object has begun its lifetime, is it created? [intro.object/1] says:
[...] An object is created by a definition ([basic.def]), by a new-expression, when implicitly changing the active member of a union ([class.union]), or when a temporary object is created ([conv.rval], [class.temporary]) [...]
So, according to this, my obj
(as an int
) is not created. But its lifetime as an int
(and as other, possibly infinite-type vacuously-initializable objects) has started.
I'm confused, can you give a clarification on this?
You cannot begin the lifetime of a object unless the object has been created. And [intro.object]/1 defines the only ways in which objects can be created:
An object is created by a definition (6.1), by a new-expression (8.3.4), when implicitly changing the active member of a union (12.3), or when a temporary object is created (7.4, 15.2).
The object created by this definition is of type char[]
. Therefore, that is the only object whose lifetime begins. And no other objects are created by this construct.
To lend credence to this interpretation, the proposal for C++20 P0593 exists whose primary purpose is to allow that very declaration to implicitly create other such objects.
Comments:
The condition in (1.2) still bothers me. Why is it there?
It is there because it cannot say "the initialization is complete" for an object that doesn't undergo initialization.
suppose, that I have a
new(obj) int
afterwards. That clearly creates anint
object. But before that,obj
has obtained the necessary storage.
No, the declaration of obj
obtained storage for an object of type char[]
. What obtains storage for the int
object being created is new(obj)
. Yes, the placement-new expression obtains storage for the object that it creates. Just like a declaration of a variable obtains storage for the object it creates.
Just because that storage happens to exist already doesn't mean it isn't being obtained.