Почему член 'float x' инициализируется с `0.'для объектов' a` и ' b` в main()? [дубликат]
На этот вопрос уже есть ответ здесь:
- значение переменной по умолчанию 8 ответов
Может ли кто-нибудь указать, какое предложение в стандарте поддерживает следующее поведение, полученное в Coliru, для фрагмента:
#include <iostream>
class A
{
int i;
float x;
public:
A() : i(10) {}
A(int i) : i(i) {}
int GetI() { return i; }
float GetF() { return x; }
};
int main()
{
A a;
A b(1);
A x{};
A y{1};
std::cout << a.GetI() << 'n';
std::cout << a.GetF() << 'n';
std::cout << b.GetI() << 'n';
std::cout << b.GetF() << 'n';
std::cout << x.GetI() << 'n';
std::cout << x.GetF() << 'n';
std::cout << y.GetI() << 'n';
std::cout << y.GetF() << 'n';
}
Код печатает:
10
0 1
0 10
0
1
0
Редактировать:
Этот абзац взят из 4-го издания TCPL, страница 490:
Для этого правила не так чисты, как нам хотелось бы. Для статически выделенные объекты (§6.4.2), правила точно такие же, как если бы вы использовали {}, таким образом, значение альфа равно {"","",0}. Однако для локальных переменных и объекты свободного хранения, инициализация по умолчанию выполняется только для члены класса type и члены встроенного типа остаются неинициализирован, поэтому значение бета равно {"","", неизвестно}.Мистер Страуструп ничего не говорит о неопределенном поведении.
4 ответа:
0
является одним из возможных произвольных значений, которые может получить неинициализированная переменная: программа имеет неопределенное поведение. Учитывая, что существует Справедливая вероятность того, что память начинается с нуля, инициализированного,0
является вероятным результатом: представление IEEE 754 для0
оказывается все нули. Однако нет никакой гарантии, что значение будет0
.
At Mat указал, что чтение неинициализированной переменной в C++ в неопределенном поведении, что означает, что все может (и, вероятно, будет, в некоторой системе) произойти.
В зависимости от вашего компилятора и его конфигурации сборки, вы получите случайное значение в x. в вашем случае это будет 0.0, но это может быть любое случайное значение, в зависимости от того, какие данные оказались в памяти x.
В C++, как правило, считается очень плохой практикой, чтобы не инициализируйте переменные-члены в конструкторе, особенно если вы не можете гарантировать, что они будут инициализированы до их чтения.
Что именно вы ожидаете от слова "неизвестный"?
0
- вполне разумное значение для неинициализированной переменной с неопределенным значением. Это просто чистая случайность.Важно то, что
float
былНе инициализирован , и в цитируемом отрывке BS не говорит о неопределенном поведении, потому что он ссылается не на синтаксис, о котором вы спрашиваете, а на агрегатную инициализацию (и ее варианты).
Это хуже, чем просто произвольное значение. Даже если предположить, что ваш компилятор просто использует значение, оставшееся в памяти, и действует на переменную нормально после этого, ранее существовавшие биты могут представлять значение ловушки с плавающей запятой и завершить вашу программу при первом доступе.
Но это выходит еще дальше. Поскольку стандарт C++ определяет преобразование lvalue - >rvalue для неинициализированных данных как неопределенное поведение, компилятору совершенно разрешено делать все, что он хочет для вашего кода, даже код, который не связан с этой переменной, и даже до первого доступа к этой переменной (до тех пор, пока он может доказать, что неопределенное чтение переменной приходит, что доказательство обычно легко только в пределах одного и того же базового блока).