Статический массив статических членов: возможность фиаско порядка инициализации

Рассмотрим следующий код:

class Foo {
public:
    static const char one[];
    static const char two[];
    static const char* all[];
};

const char Foo::one[] = "one";
const char Foo::two[] = "two";
const char* Foo::all[] = {Foo::one, Foo::two};

int main()
{
    for (const auto& x: Foo::all) {
        std::cout << x << std::endl;
    }
    return 0;
}

Если работает как положено, но я использую статические переменные (one и two) для инициализации другой статической переменной. Могу ли я столкнуться с фиаско порядка статической инициализации здесь?

Я также могу добавить constexpr ко всем объявлениям и перенести инициализацию в объявление:

class Foo {
public:
    static const constexpr char one[] = "one";
    static const constexpr char two[] = "two";
    static const constexpr char* all[] = {one, two};
};

Изменит ли это что-нибудь в отношении фиаско статического порядка инициализации?


person Petr    schedule 21.02.2019    source источник


Ответы (2)


Внутри одного TU указан порядок инициализации (сверху вниз), поэтому у вас нет проблем.

И даже если разбить по разным TU, значения не читаешь, так что тоже ок. (например, для const std::string Foo::all[] = {Foo::one, Foo::two}).

person Jarod42    schedule 21.02.2019
comment
Я не читаю значения символов, но я читаю значения указателей (поскольку Foo::one — это указатель), не так ли? - person Petr; 21.02.2019
comment
Foo::one - это массив (из 4 символов), а не указатель. Таким образом, вы инициализируете не указатель, а содержимое. Если у вас был static const char* one, то да, ваш all[0] может быть nullptr или "one" (при условии разных TU) - person Jarod42; 21.02.2019

Нет, здесь нет фиаско. Определяется порядок инициализации статических переменных в пределах одной единицы трансляции, причем в порядке их определения.

Создание constexpr изменит несколько вещей, но не порядок инициализации.

person SergeyA    schedule 21.02.2019