Урок №28. Инициализация, присваивание и объявление переменных

  Юрий  | 

  |

  Обновл. 11 Сен 2021  | 

 138130

 ǀ   22 

Этот урок является более детальным продолжением урока №10.

Адреса и переменные

Как вы уже знаете, переменные — это имена кусочков памяти, которые могут хранить информацию. Помним, что компьютеры имеют оперативную память, которая доступна программам для использования. Когда мы определяем переменную, часть этой памяти отводится ей.

Наименьшая единица памяти — бит (англ. «bit« от «binary digi), который может содержать либо значение 0, либо значение 1. Вы можете думать о бите, как о переключателе света — либо свет выключен (0), либо включен (1). Чего-то среднего между ними нет. Если просмотреть случайный кусочек памяти, то всё, что вы увидите, — будет ...011010100101010... или что-то в этом роде. Память организована в последовательные части, каждая из которых имеет свой адрес. Подобно тому, как мы используем адреса в реальной жизни, чтобы найти определенный дом на улице, так и здесь: адреса позволяют найти и получить доступ к содержимому, которое находится в определенном месте памяти. Возможно, это удивит вас, но в современных компьютерах, у каждого бита по отдельности нет своего собственного адреса. Наименьшей единицей с адресом является байт (который состоит из 8 битов).

Поскольку все данные компьютера — это лишь последовательность битов, то мы используем тип данных (или просто «тип»), чтобы сообщить компилятору, как интерпретировать содержимое памяти. Вы уже видели пример типа данных: int (целочисленный тип данных). Когда мы объявляем целочисленную переменную, то мы сообщаем компилятору, что «кусочек памяти, который находится по такому-то адресу, следует интерпретировать как целое число».

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

Кроме int, есть много других типов данных в языке C++, большинство из которых мы детально рассмотрим на соответствующих уроках.

Фундаментальные типы данных в С++


В языке C++ есть встроенная поддержка определенных типов данных. Их называют основными типами данных (или «фундаментальные/базовые/встроенные типы данных»).

Вот список основных типов данных в языке C++:

Категория Тип Значение Пример
Логический тип данных bool true или false true
Символьный тип данных char, wchar_t, char16_t, char32_t Один из ASCII-символов ‘c’
Тип данных с плавающей запятой float, double, long double Десятичная дробь 3.14159
Целочисленный тип данных short, int, long, long long Целое число 64
Пустота void Пустота

Объявление переменных

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

Принцип объявления переменных других типов аналогичен:

Объявление пяти переменных разных типов:

Обратите внимание, переменной типа void здесь нет (о типе void мы поговорим детально на следующем уроке).

Инициализация переменных


При объявлении переменной мы можем присвоить ей значение в этот же момент. Это называется инициализацией переменной.

Язык C++ поддерживает 2 основных способа инициализации переменных.

Способ №1: Копирующая инициализация (или «инициализация копированием») с помощью знака равенства =:

Способ №2: Прямая инициализация с помощью круглых скобок ():

Прямая инициализация лучше работает с одними типами данных, копирующая инициализация — с другими.

uniform-инициализация

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

В попытке обеспечить единый механизм инициализации, который будет работать со всеми типами данных, в C++11 добавили новый способ инициализации, который называется uniform-инициализация:

Инициализация переменной с пустыми фигурными скобками указывает на инициализацию по умолчанию (переменной присваивается 0):

В uniform-инициализации есть еще одно дополнительное преимущество: вы не сможете присвоить переменной значение, которое не поддерживает её тип данных — компилятор выдаст предупреждение или сообщение об ошибке. Например:

Правило: Используйте uniform-инициализацию.

Присваивание переменных


Когда переменной присваивается значение после её объявления (не в момент объявления), то это копирующее присваивание (или просто «присваивание»):

В языке C++ нет встроенной поддержки способов прямого/uniform-присваивания, есть только копирующее присваивание.

Объявление нескольких переменных

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

И:

Кроме того, вы даже можете инициализировать несколько переменных в одной строке:

Есть 3 ошибки, которые совершают новички при объявлении нескольких переменных в одном стейтменте:

Ошибка №1: Указание каждой переменной одного и того же типа данных при инициализации нескольких переменных в одном стейтменте. Это не критичная ошибка, так как компилятор легко её обнаружит и сообщит вам об этом:

Ошибка №2: Использование разных типов данных в одном стейтменте. Переменные разных типов должны быть объявлены в разных стейтментах. Эту ошибку компилятор также легко обнаружит:

Ошибка №3: Инициализация двух переменных с помощью одной операции:

Хороший способ запомнить эту ошибку и не допускать в будущем — использовать прямую или uniform-инициализацию:

Этот вариант наглядно показывает, что значение 5 присваивается только переменным b и d.

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

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

Где объявлять переменные?

Более старые версии компиляторов языка Си вынуждали пользователей объявлять все переменные в верхней части функции:

Сейчас это уже неактуально. Современные компиляторы не требуют, чтобы все переменные обязательно были объявлены в самом верху функции. В языке С++ приоритетным является объявление (а также инициализация) переменных как можно ближе к их первому использованию:

Такой стиль написания кода имеет несколько преимуществ:

   Во-первых, возле переменных, которые объявлены как можно ближе к их первому использованию, находится другой код, который способствует лучшему представлению и пониманию происходящего. Если бы переменная х была объявлена в начале функции main(), то мы бы не имели ни малейшего представления, для чего она используется. Для понимания смысла переменной пришлось бы целиком просматривать всю функцию. Объявление переменной х возле операций ввода/вывода данных позволяет нам понять, что эта переменная используется для ввода/вывода данных.

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

   И, наконец, уменьшается вероятность случайного создания неинициализированных переменных.

В большинстве случаев, вы можете объявить переменную непосредственно в строке перед её первым использованием. Тем не менее, иногда, могут быть случаи, когда это будет не желательно (по соображениям производительности) или невозможно. Детально об этом мы поговорим на следующих уроках.

Правило: Объявляйте переменные как можно ближе к их первому использованию.

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (919 оценок, среднее: 4,95 из 5)
Загрузка...

Комментариев: 22

  1. Kuchizuke:

    Пожалуйста уточните о uniform — инициализации. В uniform-инициализации я не смогу присвоить значение переменной одного типа в переменную другого типа которая требует сужающего преобразования. double в int нельзя а int в double можно, правильно?

    1. 4b6rat0r:

      Именно при попытке инициализации переменной типа int с помощью uniform — инициализации типа данных double компилятор будет жаловаться на: Error C2397 conversion from ‘double’ to ‘int’ requires a narrowing conversion.

      Но если попытаться провернуть операцию инициализации double из числа int (Пример

      ) — никакой ошибки не произойдет.

      Примерно тоже происходит с типами char и std::string.

  2. Ника:

    Программирую на плюсах в VS уже давно, но иногда нет нет, да заглядываю к истокам, чтобы освежить. Потому что это как ни странно забывается (та же терминология). Вроде используешь это вот так уже 1000 лет, а почему так, уже не волнует. Сюда зашёл, вспомнил и как-то веселей ) сайт очень хорош!

  3. Гогги:

    Просто ахриненный сайт, читаю книгу и параллельно сайт. Сайт конечно проще и информативней излагает мысль. Точнее автор. И примеры. ++ вам в карму!

  4. Андрей:

    У вас очень отличный сайт мало где такое найдёшь!!!

  5. Владимир:

    В разделе "определение переменных" вроде примеры их объявления, а не определения ))

    1. Фото аватара Юрий:

      Спасибо за замечание, всё исправил)

  6. Алексей:

    Вопрос следующий:
    ubuntu, vim, не работает uniform инициализация — типа a{2}.
    Требует с++11. Поставил, требует так же.

    1. Steindvart:

      Ubuntu и vim не имеют ничего общего с uniform-инициализацией, потому что это не C++ компиляторы.

      В этой среде, скорее всего, вами используется gcc (или gpp как подмножество для плюсов). И в него нужно передавать соответствующие параметры компиляции, в том числе стандарт.

      Делается это с помощью флага -std. Например, вот так для стандарта с++11: -std=c++11`

  7. Никита:

    Сайт отличный не только содержанием, но и быстротой с красотой. Знаю я одного ютубера PHP-шера, который якобы профессионал. Ужасное оформление своего сайта у него. Вы бы видели. Глаза кровью обливались
    p.s.: тот, который "Си за 1 час" видеоролик имеет )

    1. Фото аватара Юрий:

      Ахахах, спасибо за столь лестный отзыв. Этот сайт тоже не идеален, но вот компромиссное решение между быстротой, красотой и содержанием, кажется, удалось достигнуть.

  8. Andrey:

    Где можно скачаться весь пройденный курс? Иногда приходться находиться в таких местах, где нет интернета и нет возможности заниматься.

    1. Фото аватара Юрий:

      Я думаю немного позже, я сделаю pdf-ник с половиной курса. Потом, когда все уроки доперевожу — сделаю pdf-ник целого курса.

  9. Torgu:

    Здравствуйте, где можно скачать IDE с поддержкой C++11? Не хочется упускать возможности использования "Uniform Initialization". Хотя порограмма не старая — Visual Studio 2017

    1. Фото аватара Юрий:

      Смотрите урок 4 — в нем детально рассписывается как устанавливать Visual Studio и где скачать. Если вы скачиваете с оф. сайта и ничего лишнего в настройках не изменяете, то C++11 и uniform инициализация в Visual Studio 2017 используются по умолчанию.

  10. Виталий:

    "int value{5};"
    а здесь точно нет ошибок?
    по логике должно быть "int nValue{5};"
    или я ошибаюсь?

    1. Фото аватара Юрий:

      Это названия переменных. Имена переменных могут быть разными. Здесь они разные — не одинаковые во всех примерах.

  11. Сергей:

    Хороший урок про определение переменных, автору + 100 к карме, надеюсь сайт не умрёт и дальше будет развиваться и пополняться статьями, которые изложены в такой простой и доходчивой форме.

    1. Фото аватара Юрий:

      Будем продолжать дальше 🙂

    2. Илья:

      Поддерживаю предыдущего комментатора — сайт отличный! Автору спасибо и успехов! Супер! Надеюсь на продолжение работы по переводу!

      1. Фото аватара Юрий:

        И Вам спасибо 🙂

    3. илья:

      сайт отличный, не поспоришь!

Добавить комментарий

Ваш E-mail не будет опубликован. Обязательные поля помечены *