Значение переменной по умолчанию - PullRequest
50 голосов
/ 17 мая 2011

Если я не присваиваю значение переменной, когда я ее объявляю, по умолчанию она равна нулю или только тому, что было ранее в памяти?

например

float x;

Ответы [ 8 ]

55 голосов
/ 17 мая 2011

Объявленная переменная может быть Инициализировано нулем , Инициализировано значение или Инициализировано по умолчанию .

Стандарт C ++ 03 8.5 / 5удачно определяет каждый:

К инициализация нулями объект типа T означает:

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

К инициализация по умолчанию объект типа T означает:
- если T является типом класса, отличным от POD (пункт 9), конструктор по умолчаниюдля T вызывается (и инициализация некорректна, если T не имеет доступного конструктора по умолчанию);
- если T является типом массива, каждый элемент инициализируется по умолчанию;
- в противном случае объект равен нулюинициализируется.

К значение-инициализация объект типа T означает:
- если T является типом класса (пункт 9) с объявленным пользователем конструктором (12.1), тогда вызывается конструктор по умолчанию для T (и инициализация некорректна, если у T нет доступного конструктора по умолчанию);
- если T является типом класса без объединения без конструктора, объявленного пользователем, то каждыйнестатический член данных и компонент базового класса T инициализируются значением;
- если T является типом массива, то каждый элемент инициализируется значением;
- в противном случае объект инициализируется нулем

Например:

#include<iostream>
using namespace std;

static int a; //Zero Initialized
int b; //Zero Initialized

int main()
{
    int i;  //Undefined Behavior, Might be Initialized to anything
    static int j; //Zero Initialized

    cout<<"\nLocal Uninitialized int variable [i]"<<i<<"\n";

    cout<<"\nLocal Uninitialized Static int variable [j]"<<j<<"\n";

    cout<<"\nGlobal Uninitialized Static int variable [a]"<<a<<"\n";

    cout<<"\nGlobal Uninitialized int variable [b]"<<b<<"\n";

    return 0;
}

Вы заметите, что результаты для переменной i будут отличаться на разных компиляторах.Такие локальные неинициализированные переменные НЕ ДОЛЖНЫ использоваться .Фактически, если вы включите строгие предупреждения компилятора, компилятор сообщит об ошибке об этом.Вот как кодпад сообщает об ошибке.

cc1plus: warnings being treated as errors
In function 'int main()':
Line 11: warning: 'i' is used uninitialized in this function

Редактировать: Как справедливо отмечено @Kirill V. Lyadvinsky в комментариях, СЛЕДУЕТ НИКОГДА - довольно очень сильное слово, и тамможет быть совершенно допустимым кодом, который может использовать неинициализированные переменные, как он указывает на пример в своем комментарии.Поэтому я, наверное, должен сказать:
Никогда не следует использовать неинициализированные переменные, если вы точно не знаете, что делаете.

17 голосов
/ 17 мая 2011

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

6 голосов
/ 17 мая 2011

Это зависит от времени жизни переменной.Переменные со статическим временем жизни всегда инициализируются нулями до запуска программы: инициализация нулями для базовых типов, enum s и указателей такая же, как если бы вы присвоили ей 0, соответствующим образом преобразованный в тип.Это происходит, даже если переменная имеет конструктор перед вызовом конструктора.

4 голосов
/ 17 мая 2011

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

2 голосов
/ 17 мая 2011

Использование значения любой переменной перед инициализацией (обратите внимание, что объекты длительности статического хранения всегда инициализируются, так что это относится только к продолжительности автоматического хранения) приводит к неопределенному поведению .Это очень отличается от того, что содержит 0 в качестве начального значения или содержит случайное значение.UB означает, что может случиться что-нибудь .В реализациях с битами-ловушками это может привести к сбою вашей программы или генерации сигнала.Также возможно, что множественные чтения приводят к различным непредсказуемым значениям среди любого другого мыслимого (или невообразимого) поведения.Просто не используйте значение неинициализированных переменных .

Примечание: Следующее было отредактировано на основе комментариев:

Обратите внимание, что подобный коднедействительным, если только вы не можете убедиться, что тип foo_t не имеет битов заполнения:

foo_t x;
int i;
for (i=0; i<N; i++) x = (x<<1) | get_bit();

Даже если предполагается, что «случайное значение», первоначально в x, будет отброшено до окончания цикла,Программа может вызывать UB, как только она обращается к x для выполнения операции x<<1 на первой итерации, и, таким образом, весь вывод программы становится недействительным.

2 голосов
/ 17 мая 2011

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

2 голосов
/ 17 мая 2011

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

ОБНОВЛЕНИЕ: согласно комментариям - глобальные переменные будут инициализироваться нулями. Локальные переменные будут любыми.

Чтобы ответить на ваш второй вопрос:

Спасибо - после этого, есть ли ярлык для присвоения нуля всем следующим: плавать x1, x2, x3, x4, x5, y1, y2, y3, y4, y5

Вы могли бы сделать

float x[5] = {0,0,0,0,0}; float y[5] = {0,0,0,0,0};

и используйте x[0] вместо x1.

1 голос
/ 17 мая 2011

C ++ не создает экземпляры переменных.Значение x - это то, что было в памяти в то время.Никогда не предполагайте ничего о его первоначальном значении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...