int x; int y; int * ptr; это не инициализация, верно?
Я читаю "C++ All-in-One для чайников" Дж.П. Мюллера и Дж. Когсвелла и наткнулся на это:
#include <iostream>
using namespace std;
int main()
{
int ExpensiveComputer;
int CheapComputer;
int *ptrToComp;
...
Этот код начинается с инициализации всех задействованных вкусностей - двух целых и указателя на целое число.
Просто чтобы подтвердить, что это ошибка, она должна гласить "... объявив", верно? Мне просто странно, что такие основные ошибки все-таки попадают в книги.
Ответы
Ответ 1
С точки зрения языка это инициализация по умолчанию. Проблема в том, что они инициализируются неопределенными значениями.
в противном случае ничего не делается: объекты с автоматической продолжительностью хранения (и их подобъекты) инициализируются неопределенными значениями.
Инициализация по умолчанию для неклассовых переменных с автоматическим и динамическим сроком хранения создает объекты с неопределенными значениями (статические и локальные для потока объекты инициализируются нулем)
Обратите внимание, что любая попытка прочитать эти неопределенные значения приводит к UB.
Из стандарта, [dcl.init]/7
По умолчанию инициализировать объект типа T означает:
-
Если T является (возможно, cv-квалифицированным) типом класса ([class]), рассматриваются конструкторы. Применимые конструкторы перечисляются ([over.match.ctor]), и лучший для инициализатора() выбирается с помощью разрешения перегрузки ([over.match]). Выбранный таким образом конструктор вызывается с пустым списком аргументов для инициализации объекта.
-
Если T является типом массива, каждый элемент инициализируется по умолчанию.
-
В противном случае инициализация не выполняется.
Ответ 2
Да вы правы.
Вы объявили и определили эти переменные, вы не инициализировали их!
PS: В чем разница между определением и декларацией?
Ответ 3
Этот код объявляет и определяет три переменные, но не инициализирует их (их значения называются неопределенными).
Объявление переменной должно включать только ключевое слово extern
.
Ответ 4
Правильно. Отсюда и "чайники". :)
Мы даже не можем винить в этом наследие; исторически C программисты объявляли * переменную, а затем "инициализировали" ее позже с помощью первого присваивания.
Но никогда не считалось, что простое объявление переменной без инициализатора "инициализирует" ее **.
Так что формулировка просто неверна.
* Технически мы говорим об определениях, но когда мы говорим "объявить переменную", мы почти всегда имеем в виду определение объявлений.
** Хотя объекты со статической длительностью хранения проходят свою собственную фазу нулевой инициализации, прежде чем что-либо еще произойдет, поэтому отказ от инициализации сам по себе не является катастрофой в этом случае.Тем не менее, мы не можем утверждать, что мы инициализировали этот объект.