A recent question drew my attention to the way that constexpr
has changed in C++14. The new feature is that a non-local variable with static storage duration may be initialized in the static initialization phase if its initializer consists of a constexpr
constructor, even if the type of the variable isn't a literal type. More precisely, the new wording in [basic.start.init] is:
A constant initializer for an object
o
is an expression that is a constant expression, except that it may also invoke constexpr constructors foro
and its subobjects even if those objects are of non-literal class types [Note: such a class may have a non-trivial destructor — end note]. Constant initialization is performed [...] if an object with static or thread storage duration is initialized by a constructor call, and if the initialization full-expression is a constant initializer for the object [...]
The typical example is std::unique_ptr
, which "should never be worse that hand-written":
std::unique_ptr<int> p; // statically initialized by [unique.ptr.single.ctor],
// requires no code excution
int main()
{
p = std::make_unique<int>(100);
}
// p is destroyed eventually
Prior to this addition, statically initialized variables were either of reference type or of literal object type, and therefore had trivial destructors. But now a statically initialized global variable can have a non-trivial destructor.
How is such a destructor call ordered with respect to the destructors of dynamically initialized global objects, with respect to other statically initialized ones, and how are the destructor calls sequenced?
std::mutex
has aconstexpr
constructor so that it can take advantage of static initialization, for instance.) – Louiselouisette