Question

When are constexpr objects constructed relative to non-constexpr non-local objects with static storage duration? Do they start their life prior to initialization of any other objects, i.e., prior to dynamic initialization?

I'm contemplating whether it would be reasonable to have a string_literal class (live example) which is used, e.g., to compare std::strings against certain keywords:

class string_literal
{
    // private members
public:
    constexpr string_literal(char const* b);
    bool operator== (std::string const& other) const;
    bool operator!= (std::string const& other) const;
    // other member functions
};

constexpr string_literal hello("hello");
void f(std::string const& s) {
    if (s == hello) {
        // do something
    }
}

Since the string_literal could parse the string-literal at compile-time to locate the first null-character, I could imagine that these comparisons can be made faster than comparing a std::string against a string-literal. However, to be safe it is necessary that the hello object is readily constructed when the first constructor is executed at run-time during static initialization: otherwise these objects could be accidentally accessed when they are not, yet, constructed.

Was it helpful?

Solution

In the C++11 standard the order of initialization of non-local variables is discussed in §3.6.2 “Initialization of non-local variables”.

First static initialization is performed, then dynamic initialization.

Static initialization consists of zero-initialization followed by constant-initialization. Zero-initialization is just what it sounds like. Constant-initialization is new in C++11, and §3.6.2/2 specifies that it's performed

  • if each full-expression (including implicit conversions) that appears in the initializer of a reference with static or thread storage duration is a constant expression (5.19) and the reference is bound to an lvalue designating an object with static storage duration or to a temporary (see 12.2);
  • if an object with static or thread storage duration is initialized by a constructor call, if the constructor is a constexpr constructor, if all constructor arguments are constant expressions (including conversions), and if, after function invocation substitution (7.1.5), every constructor call and full-expression in the mem-initializers and in the brace-or-equal-initializers for non-static data members is a constant expression;
  • if an object with static or thread storage duration is not initialized by a constructor call and if every full-expression that appears in its initializer is a constant expression.

So, the second point is where a constexpr object is potentially initialized, as the last part of static initialization, and essentially it happens if everything is constexpr so that it can be known at compile time.

And yes, as part of the static initialization this happens before dynamic initialization.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top