During a dive into dynamic memory, it occurred to me it appears contradictory how trivial types begin their lifetime. Consider the snippet
void* p = ::operator new(sizeof(int)); // 1
// 2
new (p) int; // 3
When does the int
start its lifetime?
Only acquires storage,
::operator new
is specified to have the effect (from [new.delete.single])The allocation functions called by a new-expression to allocate size bytes of storage. [...] allocates storage suitably aligned to represent any object of that size provided the object's type does not have new-extended alignment.
Given that acquiring storage is insufficient in creating an object, the
int
cannot have begin its lifetime here.At this point, suitbale storage for the
int
has been acquired.The
int
is created by placement new. But somehow its lifetime didn't begin here, since from [basic.life][...] 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. The lifetime of an object of type
T
begins when:storage with the proper alignment and size for type
T
is obtained, andif the object has non-vacuous initialization, its initialization is complete [...]
int
is neither a class nor aggregate type, hence it has vacuous initialization. Therefore only the first bullet applies. However, this is clearly not when storage is obtained and therefore cannot be when its lifetime starts.
Some context
Allocators are required to return memory without constructing its elements. Yet this doesn't make sense with trivial types. The effects of a.allocate(n)
with a
an allocator object for type T
is
Memory is allocated for
n
objects of typeT
but objects are not constructed.
memcpy
or whatever) . The original title of this thread was misleading as to the real issue it raises – Thomanew
is what causes the object to be created, pursuant to [intro.object]/1. You cannot start the lifetime of an object that doesn't exist. – Mariko