According to this and this an aggregate is implicit lifetime.
A class S is an implicit-lifetime class if it is an aggregate or has at least one trivial eligible constructor and a trivial, non-deleted destructor.
And implicit lifetime objects can be created with malloc. See this example.
#include <cstdlib>
struct X { int a, b; };
X* MakeX()
{
// One of possible defined behaviors:
// the call to std::malloc implicitly creates an object of type X
// and its subobjects a and b, and returns a pointer to that X object
X* p = static_cast<X*>(std::malloc(sizeof(X)));
p->a = 1;
p->b = 2;
return p;
}
But struct A {std::string s;};
is also an aggregate. But this produces an exception as I expected since the assignment to s would first destruct s and s is not valid as it was never constructed.
#include <cstdlib>
#include <string>
#include <iostream>
struct X { std::string s; };
X* MakeX()
{
X* p = static_cast<X*>(std::malloc(sizeof(X)));
p->s = "abc";
return p;
}
int main()
{
static_assert(std::is_aggregate_v<X>);
auto x = MakeX();
std::cout << x->s << "\n";
}
So why is an aggregate considered an implicit lifetime type?
struct X
is an aggrigate; the lifetime ofstd::string s;
has not been started (still working through various standard changes). – Roadhouses
subobject does not have its lifetime started (becausestring
is not implicit-lifetime). – Exeterconstruct_at
is required to start the lifetime of a contained object. – Oxbridge