Урок 28. Детальнее об инициализации, присвоении и определении

   ⁄ 

 Обновлено 17 Апр 2017

  ⁄   

⁄  4

Этот урок является более детальным продолжением темы Урока 10. Переменные, инициализация и присваивание в С++.

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

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

На следующем рисунке показаны примеры последовательных адресов памяти, наряду с соответствующими байтами данных:

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

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

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

Основные типы данных в С++

В C++ есть встроенная поддержка определенных типов данных. Они называются основные типы данных, но часто, неофициально, их еще называют базовые, примитивные или встроенные типы данных.

Вот список основных типов данных (с некоторыми вы уже сталкивались раньше):

Категория Тип Значение Пример Примечание
boolean bool true или false true
character char, wchar_t, char16_t, char32_t один из ASCII-символов ‘c’ char16_t, char32_t только в C++11
floating point float, double, long double десятичная дробь 3.14159
integer short, int, long, long long целое число 64 long long только в C99/C++11
void нет типа пустота

Эта глава уроков как раз посвящена детальному изучению основных типов данных в С++.

Определение переменной

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

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

А здесь мы определили 5 различных переменных 5 различных типов:

Обратите внимание, void-а здесь нет, так как он имеет другое предназначение и другие правила использования (об этом в отдельном уроке).

Инициализация переменной

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

C++ поддерживает два основных способа инициализации переменных. Первый: copy initialization (копирующая инициализация) с помощью знака равенства:

Второй: direct initialization (прямая инициализация) с помощью круглых скобок.

Прямая инициализация может работать лучше для некоторых типов данных, нежели копирующая инициализация. Также она имеет и некоторые другие преимущества, о которых мы расскажем, когда будет изучать классы. Мы рекомендуем использовать direct initialization вместо copy initialization.

Правило: Используйте прямую инициализацию вместо копирующей.

Uniform initialization в С++

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

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

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

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

Uniform initialization еще иногда называют list initialization.

Правило: Если вы пользуетесь компилятором, поддерживающим C++ 11, используйте uniform initialization.

Присваивание переменной

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

В C++ нет встроенной поддержки форм direct или uniform присваивания, только copy.

Неинициализированные переменные

Переменная, которая не инициализирована, называется неинициализированной переменной. В C++, значением неинициализированной переменной будет всякий мусор, до тех пор, пока вы не присвоите ей нормальное значение. Мы об этом рассказывали в предыдущем уроке о переменных.

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

Определение нескольких переменных

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

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

Но есть три ошибки, которые совершают начинающие программисты при определении нескольких переменных в одном стейтменте.

Первая ошибка: указание одного типа для каждой переменной отдельно. Это не такая уж ужасная ошибка, так как компилятор легко её обнаружит и сообщит об этом.

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

А вот третью ошибку (опасная) программист допускает, когда пытается инициализировать две переменные, используя одну инициализацию:

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

Лучшим способом запомнить, что это неправильно — использовать direct или uniform инициализацию:

Так более понятно, что значение 5 присвоено только переменной b.

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

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

Где определять переменные

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

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

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

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

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

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

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

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

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

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (23 оценок, среднее: 5,00 из 5)
Загрузка...
Поделиться в:
Подписаться на обновления:

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

  1. Сергей:

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

    1. Li4ik:

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

    2. Илья:

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

      1. Li4ik:

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

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

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