В C ++ простые фиктивные инициализации встроенного типа неуязвимы для статического порядка инициализации?

Я знаю о статический порядок инициализации фиаско в C ++ и
построить при первом использовании идиома чтобы избежать этого. Таким образом, в коде ниже
глобальное назначение a может случиться до того foo::a так что
значение a не определено С другой стороны, глобальный
назначение b все в порядке, так как он вызвал функцию foo::b(),

#include <iostream>
#include <string>

using namespace std;

// foo.hpp

class foo {
public:
static const string a;
static const string& b();
static const char* const c;
static const char* const d[2];
static const int e;
static const int f[2];
};

// foo.cpp

const string foo::a("astr");
const string& foo::b() {
static const string t("bstr");
return t;
}
const char* const foo::c = "cstr";
const char* const foo::d[2] = {"dstr1", "dstr2"};
const int foo::e = 5;
const int foo::f[2] = {6, 7};

// main.cpp

// global initializations
string a = foo::a;              // dangerous, might be "" or "astr"string b = foo::b();            // safe, guaranteed to be "bstr"const char* c = foo::c;         // what about these...?
const char* d = foo::d[0];
int e = foo::e;
int f = foo::f[0];

int main() {
cout << a << " " << b << "\n"<< c << " " << d << "\n"<< e << " " << f << "\n";
}

(Представь, что я объединил foo.hpp, foo.cpp, а также main.cpp Вот.)
Однако как насчет переменных, которые являются встроенными типами или массивами из них?
Таким образом, глобальные назначения c, d, e, а также f безопасно в этом коде?
Кажется возможным, что компоновщик может установить память для этих переменных
поэтому во время выполнения инициализация не требуется. Но могу ли я положиться на
этот?

Я знаю, что я не должен использовать глобальные переменные. Тем не менее, я автор
библиотеки (foo.cpp и foo.hpp), и я не имею никакого контроля над тем, что
пользователь моей библиотеки (автор main.cpp) делает.

0

Решение

Ключевым моментом здесь является разница междуstatic «инициализация» (формально известный с использованием языка Стандарта как динамическая инициализация объектов со статической продолжительностью хранения который имеет фиаско заказа) и статическая инициализация.

Стандарт говорит (раздел [basic.start.static]) тот

Постоянный инициализатор для объекта o является выражением, которое является константным выражением, за исключением того, что оно также может вызывать constexpr конструкторы для o и его подобъекты, даже если эти объекты не литеральных типов классов. [Примечание: у такого класса может быть нетривиальный деструктор — примечание конца]

Постоянная инициализация выполняется:

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

Если постоянная инициализация не выполняется, переменная со статической продолжительностью хранения или продолжительностью хранения потока инициализируется нулями. Вместе нулевая инициализация и постоянная инициализация называются статической инициализацией; все остальные инициализации — это динамическая инициализация. Статическая инициализация должна быть выполнена до любой динамической инициализации.

Ваш c, d, e, а также f объекты имеют постоянные инициализаторы, поэтому их инициализация завершается на этапе статической инициализации (даже если c а также d сами по себе НЕ являются постоянными), и их значения доступны во время всей динамической инициализации, даже те, которые были лексически раньше.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]