У меня возникли некоторые сомнения после обсуждения этого с коллегами …
Как следует из заголовка, когда можно предположить, что встроенные типы будут инициализированы в 0 вместо неизвестного значения?
Различаются ли правила в стандартах c ++?
Полные правила находятся в [dcl.init] (C ++ 11). Подводя итог: если в объявлении не указан инициализатор, сущность называется по умолчанию инициализирован. Для типов классов это означает, что вызывается конструктор по умолчанию. Для не классовых типов это означает инициализация не выполняется.
Однако в [dcl.init] § 9 говорится: «Каждый объект статической длительности хранения инициализируется нулями при запуске программы перед любой другой инициализацией».
Это означает, что переменные статической длительности (например, переменные пространства имен) не-классового типа инициализируются нулями. Другие объекты не-классовых типов (например, локальные переменные) не инициализирован.
Вместо того, чтобы отвечать на конкретный вопрос, который вы публикуете, на который уже был дан ответ: только объекты 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
}
Согласно обоим С ++ 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
Я бы не предполагал, что любой неявный тип будет инициализирован равным 0. Вы можете обнаружить, что это тот случай, когда вы работаете внутри отладчика и используете кучу / стек отладки. Когда вы находитесь за пределами отладчика или отключаете кучу отладки с помощью переменной среды _NO_DEBUG_HEAP = 1, или иначе вы обнаружите, что память в большинстве случаев не инициализируется.
Как правило, инициализируйте ваши переменные, так как программировать безопаснее.
РЕДАКТИРОВАТЬ: Как указывает Лучиан Григоре, глобальные переменные области видимости являются исключением. Они также часто не работают с проверками неинициализированных переменных из-за этой инициализации.