Как локальные и глобальные переменные инициализируются по умолчанию? - PullRequest
10 голосов
/ 24 августа 2010

Исходя из приведенного ниже, я прав?

  • ссылка global_A инициализирована на ноль.
  • global_int равен 0
  • ссылка local_A равна нулю
  • local_int неинициализирован
  • И global_A.x, и local_A.x не инициализированы.

Спасибо за любую помощь.


A global_A;
int global_int;

class A {
  public : int x;
}

int main()
{
  int local_int;
  A local_A;
}

Ответы [ 10 ]

13 голосов
/ 24 августа 2010

Опираясь на ответ Андрея.

$ 3.6.2- «Объекты со статической продолжительностью хранения (3.7.1) должны быть инициализированы нулями (8.5) перед любой другой инициализацией». В OP «global_A» и «global_int» имеют статическую продолжительность хранения. «local_int» и «local_A» не имеют связи, так как это локальные объекты.

$ 8,5 / 5- Инициализация объекта типа T с нуля означает:

- если T скалярный тип (3.9), для объекта установлено значение 0 (ноль) преобразуется в T;

- если T является типом класса, не являющимся объединением, каждый нестатический элемент данных и каждый подобъект базового класса zeroinitialized; * +1010 *

- если T является типом объединения, объект первый названный член данных89) нулевой инициализируется;

- если T является типом массива, каждый элемент инициализируется нулями;

- если T является ссылочным типом, нет инициализация выполнена.

$ 6.7.4 / 4- "Инициализация нуля (8.5) всех локальных объектов со статической продолжительностью хранения (3.7.1) выполняется перед любой другой инициализацией. Локальный объект типа POD (3.9) со статической продолжительность хранения, инициализированная с помощью константных выражений, инициализируется до первого ввода ее блока. ранняя инициализация других локальных объектов со статической продолжительностью хранения в тех же условиях, в которых реализация может статически инициализировать объект со статической продолжительностью хранения в области пространства имен (3.6.2). В противном случае такой объект инициализируется при первом прохождении управления через его объявление; такой объект считается инициализированным по завершении его инициализации. Если инициализация завершается с выдачей исключения, инициализация не завершена, поэтому она будет повторена при следующем входе элемента управления в объявление. Если элемент управления повторно входит в объявление (рекурсивно) во время инициализации объекта, поведение не определено. "

РЕДАКТИРОВАТЬ 2:

$ 8,5 / 9- "Если инициализатор не указан для объекта, а объект (возможно cv-квалифицирован) класс не POD (или его массив), объект должен быть по умолчанию инициализируется; если объект константного типа, базовый тип класса должен иметь объявленный пользователем конструктор по умолчанию. В противном случае, если для нестатического объекта не указан инициализатор, объект и его подобъекты, если таковые имеются, иметь неопределенный начальный value90) ; если объект или любой из его подобъекты имеют постоянную квалификацию типа, программа некорректна. "

В общем, вы хотите прочитать эти разделы вместе с 8,5 долл. США для хорошего понимания этого аспекта.

7 голосов
/ 24 августа 2010

В вашем коде нет ссылок, поэтому любые ваши пункты, в которых упоминаются "ссылки", не имеют смысла.

В вашем примере оба глобальных объекта - global_int и global_A - инициализируются нулями. Оба локальных объекта - local_int и local_A - содержат неопределенные значения, что означает, что local_int и local_A.x не инициализированы.

P.S. Конечно, как уже отмечалось, ваш код не компилируется. Вы не можете объявить A объекты до объявления class A (и вам не хватает ; после определения класса).

7 голосов
/ 24 августа 2010

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

Типы уровня языка (например, указатели, 'int', 'float', 'bool' и т. Д.) "Конструктор по умолчанию" абсолютно ничего не делает, он просто оставляет память такой, какой она есть, когда она объявлена ​​(глобальные / статические переменные в особых случаях см. ответ chubsdad для получения дополнительной информации). Это означает, что они могут быть в значительной степени чем угодно, потому что вы обычно не можете быть уверены, что было в этой памяти ранее или даже откуда она взялась (за исключением случая оператора размещения нового).

У созданного вами класса нет конструкторов, поэтому компилятор сгенерирует для вас конструктор по умолчанию, который просто вызывает конструктор каждого из его членов / переменных. Если вы включите информацию, представленную в предыдущем абзаце, вы увидите, что для переменной 'x' будет вызываться конструктор по умолчанию, который ничего не делает и, следовательно, не инициализируется каким-либо значением.

Как уже говорили другие, в вашем коде или указателях нет ссылок, поэтому термин «NULL» здесь недопустим во всех случаях. NULL обычно относится к указателю, который, как и другие типы уровня языка, не устанавливается ни к чему, пока вы не назначите ему значение (если, конечно, это не глобальная / статическая переменная).

3 голосов
/ 24 августа 2010

Просто ради полноты, если у вас были ссылки:

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

1 голос
/ 24 августа 2010
A global_A;

Это установщик, а не указатель, ваша программа вызовет конструктор перед вводом main.

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

A* global_A;

global_int инициализируется в 0, так как все глобальные переменные инициализируются по умолчанию.

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

Как и раньше, если вы хотите указатель на A, вы должны написать A * local_A, но на этот раз вы должны инициализировать его в NULL самостоятельно.

A *local_A = NULL;

varialle local_int не будет инициализироваться, так как это тип примитива.

Если инициализируется local_A.x, зависит от конструктора A, конструктор по умолчанию не будет инициализировать local_A.x.Если x, где экземпляр класса, создающий экземпляр A, инициализирует x конструктором своего класса.

1 голос
/ 24 августа 2010

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

0 голосов
/ 25 августа 2010

ну, ребята .. я больше сбит с толку, поскольку я вижу ответы отсюда. Во всяком случае, я сделал тест, как показано ниже:

1 #include

  2 using namespace std;
  3 
  4 class A {
  5 
  6 public :
  7         A() : x(9) {};
  8         int x;
  9 
 10 };
 11 
 12 A global_a;
 13 int global_b;
 14 
 15 int main() {
 16 
 17         A local_a;
 18         int local_b;
 19         cout << "global_a.x = " << global_a.x << '\n';
 20         cout << "local_a.x = " << local_a.x << '\n';
 21 
 22         cout << "global_b = " << global_b << '\n';
 23         cout << "local_b = " << local_b << '\n';
 24 
 25 }

Результаты с использованием моего компилятора g ++ на Ubuntu Linux:

global_a.x = 9

local_a.x = 9

global_b = 0

local_b = 0

Я думаю, что local_b должен быть неопределенным, но каким-то образом компилятор инициализировал его по умолчанию. Однако local_a .. я не уверен, что это должно быть инициализировано по умолчанию. Из тестирования здесь .. local_a похоже инициализирован. Не уверен, что это соответствует стандартной спецификации c ++ (например, в C ++ PRimer 4th edition говорится, что конструктор по умолчанию используется независимо от того, где объявлена ​​переменная класса - означает ли это, что переменная типа type инициализируется, является ли она глобальной или локальной?).

Что бы это ни было ... это один большой адский беспорядок. Может быть, я должен бросить учиться C ++. Java намного проще. Черт, дааааа !!

0 голосов
/ 24 августа 2010

Этот код не скомпилируется, если вы не отправите объявление A.

global_A ссылка инициализируется нулем - Нет, она будет ссылаться на объект A. global_int равен 0 - думаю, нужно проверить. Ссылка на local_A равна нулю - Нет, как и в случае global_A. local_int неинициализирован - да, он получит некоторое значение мусора. И global_A.x, и local_A.x не инициализированы - Да.

Вы всегда можете отладить и убедиться сами.

0 голосов
/ 24 августа 2010

ссылка global_A инициализируется в нуль.

Нет, это допустимый объект (созданный на основе конструктора по умолчанию, которого у вас нет в коде, но компилятор добавляет его)

global_int равен 0

да

local_A ссылка нулевая

нет, та же причина, что и для глобального

local_int не инициализирован

нет, его инициализировано 0

И global_A.x, и local_A.x неинициализированный.

нет, оба инициализируются в 0

0 голосов
/ 24 августа 2010

Все они требуют инициализации.Компилятор выдаст вам предупреждение об этом.

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