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 является типом массива, каждый элемент инициализируется по умолчанию.

  • В противном случае инициализация не выполняется.

Ответ 3

Этот код объявляет и определяет три переменные, но не инициализирует их (их значения называются неопределенными).

Объявление переменной должно включать только ключевое слово extern.

Ответ 4

Правильно. Отсюда и "чайники". :)

Мы даже не можем винить в этом наследие; исторически C программисты объявляли * переменную, а затем "инициализировали" ее позже с помощью первого присваивания.

Но никогда не считалось, что простое объявление переменной без инициализатора "инициализирует" ее **.

Так что формулировка просто неверна.

* Технически мы говорим об определениях, но когда мы говорим "объявить переменную", мы почти всегда имеем в виду определение объявлений.

** Хотя объекты со статической длительностью хранения проходят свою собственную фазу нулевой инициализации, прежде чем что-либо еще произойдет, поэтому отказ от инициализации сам по себе не является катастрофой в этом случае.Тем не менее, мы не можем утверждать, что мы инициализировали этот объект.