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::string
s 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.
A constexpr function is one whose return value is computable at compile time when consuming code requires it. Consuming code requires the return value at compile time to initialize a constexpr variable, or to provide a non-type template argument.
A constructor that is declared with a constexpr specifier is a constexpr constructor. Previously, only expressions of built-in types could be valid constant expressions. With constexpr constructors, objects of user-defined types can be included in valid constant expressions.
A constexpr (or indeed, any kind of variable) need not be stored anywhere if its address is never taken. A constexpr in global or namespace ,when I address it,it should store in .
constexpr stands for constant expression and is used to specify that a variable or function can be used in a constant expression, an expression that can be evaluated at compile time. The key point of constexpr is that it can be executed at compile time.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With