Перейти к содержимому
Теория · Переменные и типы · урок 2 из 9

Инициализация: =, () и {}

Значение, которое переменная получает при объявлении, называют начальным, а сам этот шаг — инициализацией. Это то, что кладут в коробку в тот момент, когда наклеивают на неё имя. Если значение не подходит к типу переменной, компилятор сам его преобразует, и часть значения может пропасть:

C++
#include <iostream>

int main() {
    double price = 2.9;
    int whole = price;
    std::cout << whole << '\n';  // 2
}

int хранит только целые числа, поэтому дробная часть 0.9 отбрасывается — без округления. Это похоже на коробку для целых плиток: от плитки 2.9 отламывают кусок 0.9, и в коробку ложится 2. Компилятор не сообщает ни об ошибке, ни о предупреждении, и программа печатает 2.

Три формы записи

Начальное значение можно записать тремя способами:

C++
int a = 5;
int b(5);
int c{5};
std::cout << a << ' ' << b << ' ' << c << '\n';  // 5 5 5
  • int a = 5; — форма со знаком =, привычная и самая частая;
  • int b(5); — форма с круглыми скобками;
  • int c{5}; — форма с фигурными скобками.

Для int и 5 все три строки делают одно и то же. Различаются они тем, как обращаются с неподходящим значением: = и круглые скобки его преобразуют, как в примере выше.

Пустые фигурные скобки задают ноль: int total{}; значит то же, что int total{0};. Чем фигурные скобки лучше двух других форм, показывает следующий пример.

Скобки против сужения

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

  • дробное число попадает в целый тип;
  • число не помещается в новый тип.

Важен не размер типа в байтах, а то, может ли пропасть часть значения. Фигурные скобки сужение запрещают:

C++
int count{2.5};  // ✗
TEXT
error: type 'double' cannot be narrowed to 'int' in initializer list [-Wc++11-narrowing]

Это ошибка компиляции: программа не соберётся, пока значение не исправят.

Целую константу, которая точно помещается в новый тип, скобки пропускают: double ratio{2}; компилируется. А дробное значение в целый тип скобки не пропускают никогда, даже 2.0: int n{2.0}; тоже не скомпилируется. Поэтому сужением будет и int whole{price}; из первого примера.

Фигурные скобки — самая строгая из трёх форм: ошибку с типом они находят сразу. Этот вопрос часто задают на собеседовании: чем int x{2.5}; отличается от int x = 2.5;.

Тип из начального значения

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

  • auto count = 10; даёт int;
  • auto price = 2.5; даёт double;
  • auto ratio = 2.5f; даёт float.

Тип берётся из начального значения, поэтому без него auto не работает: auto total; не скомпилируется.

С auto можно незаметно получить не тот тип. Если дробную сумму начать с auto total = 0;, литерал 0 даст int. Тогда присваивание total = total + 2.5; сохранит в total только 2, а компилятор промолчит. Нужен литерал подходящего типа: auto total = 0.0;.

Частая ошибка

Переменную объявили без начального значения, а потом прочитали:

C++
int total;
total = total + 5;  // ✗
TEXT
warning: variable 'total' is uninitialized when used here [-Wuninitialized]

Если переменную внутри функции объявили без начального значения, её значение не определено. Это та самая коробка, в которой лежит непредсказуемое значение. Чтение такого значения — неопределённое поведение: стандарт C++ не говорит, что сделает программа. Компилятор только предупреждает, поэтому задавайте значение сразу: int total{0}; или int total{};.

Главное

  • Инициализация задаёт начальное значение; = и круглые скобки молча преобразуют неподходящее значение, и дробная часть пропадает.
  • Фигурные скобки запрещают сужение: int n{2.0}; и int whole{price}; не скомпилируются, а double ratio{2}; — да.
  • auto берёт тип из начального значения: auto total = 0; — это int.
  • Переменную без начального значения читать нельзя, поэтому задавайте значение сразу, например int total{};.

Подпишись, чтобы пройти курс

Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.

Войти другим способом