инициализация — когда неявные типы C ++ инициализируются в 0?

У меня возникли некоторые сомнения после обсуждения этого с коллегами …

Как следует из заголовка, когда можно предположить, что встроенные типы будут инициализированы в 0 вместо неизвестного значения?

Различаются ли правила в стандартах c ++?

6

Решение

Полные правила находятся в [dcl.init] (C ++ 11). Подводя итог: если в объявлении не указан инициализатор, сущность называется по умолчанию инициализирован. Для типов классов это означает, что вызывается конструктор по умолчанию. Для не классовых типов это означает инициализация не выполняется.

Однако в [dcl.init] § 9 говорится: «Каждый объект статической длительности хранения инициализируется нулями при запуске программы перед любой другой инициализацией».

Это означает, что переменные статической длительности (например, переменные пространства имен) не-классового типа инициализируются нулями. Другие объекты не-классовых типов (например, локальные переменные) не инициализирован.

6

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

Вместо того, чтобы отвечать на конкретный вопрос, который вы публикуете, на который уже был дан ответ: только объекты POD со статическим хранилищем будут инициализированы в 0 автоматически, Я постараюсь предоставить фрагменты кода, чтобы компилятор инициализировал для вас элементы:

struct POD {
int    a;
double b; //...
};
// namespace level:
POD p;
void f() {
POD n1;                  // uninitialized
POD p1 = {};
POD p2 = POD();
POD* n2 = new POD;       // uninitialized
POD* pp1 = new POD();
delete n2; delete pp1;
}

В приведенных выше примерах не будут инициализированы только те, которые отмечены как «неинициализированные». Обратите внимание, что это в отношении того, что стандартные мандаты, ваш пробег будет варьироваться в зависимости от разных компиляторов. В частности, VS имеет некоторые проблемы с T t = T(); а также T* p = new T()' в некоторых сценариях (IIRC, когда тип T не является POD, но не имеет предоставленного пользователем конструктора по умолчанию, компилятор не сможет инициализировать подобъекты POD:

struct T {
std::string s;
int         i;
};
void f() {
T t = T();    // t.i == 0 according to the standard
}
3

Теория:

Согласно обоим С ++ 98 а также C ++ 03 стандарты:

3.6.2 Инициализация нелокальных объектов, §1:

Объекты со статической продолжительностью хранения (3.7.1) должны быть инициализированы нулями (8.5) перед любой другой инициализацией.

3.7.1 Статическая продолжительность хранения, §1:

Все объекты, которые не имеют ни динамической длительности хранения, ни являются локальными статическая продолжительность хранения.

3.7.1 Статическая продолжительность хранения, §3:

Ключевое слово static может использоваться для объявления локальной переменной со статической продолжительностью хранения.

А также 8.5 Инициализаторы, §6:

Каждый объект статической длительности хранения должен быть инициализирован нулем при запуске программы перед любой другой инициализацией.

Это одинаково в обоих стандартах. Разница лишь в формулировке C ++ 98’s 8.5 §6:

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


Пример:

Вот пример, где x а также y и имеют статическую продолжительность хранения, таким образом, стандарт гарантирует, что оба они будут инициализироваться нулем при запуске программы. Обратите внимание, что есть также объекты POD a а также b объявлен таким же образом, таким образом, имеет статическую продолжительность хранения, что означает, что их члены (i а также d) будет также инициализироваться нулями:

struct POD {
int i;
double d;
};

int x;
POD a;

int foo() {
static int y;
return y;
}

int main() {
static POD b;
std::cout << "x   = " << x      << std::endl;
std::cout << "y   = " << foo()  << std::endl;
std::cout << "a.i = " << a.i    << std::endl;
std::cout << "b.d = " << b.d    << std::endl;
}

Вывод этого примера тогда, конечно,

x   = 0
y   = 0
a.i = 0
b.d = 0
3

Я бы не предполагал, что любой неявный тип будет инициализирован равным 0. Вы можете обнаружить, что это тот случай, когда вы работаете внутри отладчика и используете кучу / стек отладки. Когда вы находитесь за пределами отладчика или отключаете кучу отладки с помощью переменной среды _NO_DEBUG_HEAP = 1, или иначе вы обнаружите, что память в большинстве случаев не инициализируется.

Как правило, инициализируйте ваши переменные, так как программировать безопаснее.

РЕДАКТИРОВАТЬ: Как указывает Лучиан Григоре, глобальные переменные области видимости являются исключением. Они также часто не работают с проверками неинициализированных переменных из-за этой инициализации.

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