Когда построены объекты constexpr?

Когда объекты constexpr построены относительно не-t20 > нелокальных объектов со статической продолжительностью хранения? Они начинают свою жизнь до инициализации любых других объектов, то есть до динамической инициализации?

Я размышляю, было бы разумно иметь string_literal класс (живой пример), который используется, например, для сравнения std::string с определенным ключевые слова:

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
    }
}

Поскольку string_literal мог анализировать строковый литерал во время компиляции, чтобы найти первый нулевой символ, я мог представить, что эти сравнения можно сделать быстрее, чем сравнение std::string с строковым литералом. Однако, чтобы быть в безопасности, необходимо, чтобы объект hello был легко сконструирован, когда первый конструктор выполняется во время выполнения во время статической инициализации: в противном случае эти объекты могут случайно получить доступ, если они еще не сконструированы.

Ответ 1

В стандарте С++ 11 порядок инициализации нелокальных переменных обсуждается в п. 6.3.2 "Инициализация нелокальных переменных".

Выполняется первая статическая инициализация , затем динамическая инициализация.

Статическая инициализация состоит из нулевой инициализации, за которой следует константа-инициализация. Нулевая инициализация - это то, на что это похоже. Константа-инициализация является новой в С++ 11, а в §3.6.2/2 указано, что она выполняла

  • если каждое полное выражение (включая неявные преобразования), которое появляется в инициализаторе ссылки со статикой или длительностью хранения потоков, является постоянным выражением (5.19), и ссылка привязана к значению l, обозначающему объект со статической продолжительностью хранения или к временному (см. 12.2);
  • если объект со статикой или длительностью хранилища потоков инициализируется вызовом конструктора, если конструктор является конструктором constexpr, если все аргументы конструктора являются постоянными выражениями (включая преобразования) и если после замены вызова функции (7.1).5), каждый вызов конструктора и полное выражение в mem-инициализаторах и в элементарных элементах для нестатических данных являются константой выражение;
  • если объект со статикой или длительностью хранения потока не инициализируется вызовом конструктора, и если каждое полное выражение, которое появляется в его инициализаторе, является постоянным выражением.

Итак, вторая точка - это то, где объект constexpr потенциально инициализируется, как последняя часть статической инициализации, и, по существу, это происходит, если все constexpr, так что оно может быть известно во время компиляции.

И да, как часть статической инициализации это происходит до динамической инициализации.