У меня возникли некоторые сомнения после обсуждения этого с коллегами...
Как следует из заголовка, когда можно предположить, что встроенные типы будут инициализированы 0 вместо неизвестного значения?
Различаются ли правила в стандартах С++?
У меня возникли некоторые сомнения после обсуждения этого с коллегами...
Как следует из заголовка, когда можно предположить, что встроенные типы будут инициализированы 0 вместо неизвестного значения?
Различаются ли правила в стандартах С++?
Полные правила находятся в [dcl.init] (C++11). Подводя итог: когда в объявлении не указан инициализатор, объект является так называемым инициализированным по умолчанию. Для типов классов это означает, что вызывается конструктор по умолчанию. Для неклассовых типов это означает, что инициализация не выполняется.
Однако в [dcl.init] §9 говорится: «Каждый объект статической продолжительности хранения инициализируется нулями при запуске программы до того, как произойдет любая другая инициализация».
Это означает, что переменные статической длительности (например, переменные области видимости пространства имен) неклассового типа инициализируются нулями. Другие объекты неклассовых типов (например, локальные переменные) не инициализируются.
int x = int();
Да, это действительно будет инициализировано до 0. Обратите внимание, что в моем ответе говорится, что инициализатор не указан. Если вы его предоставите, он, конечно же, будет им инициализирован.
- person Angew is no longer proud of SO; 08.02.2013
Вместо того, чтобы отвечать на точный вопрос, который вы публикуете, на который уже был дан ответ: только объекты 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
}
int
станут 0
, если в коде, так сказать, не упоминается 0
.
- person Drew Dormann; 08.02.2013
int x;
гарантирует, что x
равно 0, и ответ на этот вопрос только если x
имеет статическое хранилище. Другой вопрос: при объявлении переменной x
типа int
как я могу убедиться, что она инициализирована, если я не укажу явное значение?, и этот ответ содержит различные формы синтаксиса, которые вы можете используйте для инициализации значения.
- person David Rodríguez - dribeas; 09.02.2013
int x;
, то мой вопрос очень распространен. Я подозреваю, что мне следовало спросить об обратном: Когда создаются неявные типы с неизвестным значением? Тогда появляется статическое хранилище, но то же самое будет и с вашими точками, а возможно, и с другими.
- person Drew Dormann; 09.02.2013
В соответствии со стандартами C++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 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, или иным образом, вы обнаружите, что в большинстве случаев память не инициализируется.
Как правило, инициализируйте свои переменные, так как программировать таким образом безопаснее.
РЕДАКТИРОВАТЬ: Как указал Лучиан Григоре, глобальные переменные области видимости/пространства имен являются исключением. Они также часто не работают с проверками неинициализированных переменных из-за этой инициализации.
vector<int> v(10)
действительно 0 инициализирует егоint
s. - person Chris Hartman   schedule 09.02.2013