Гайд Перевод Learncpp.com: раздел 1.4 // Присваивание и инициализация переменных. На русском.

Dreammmless.
Эксперт
Статус
Оффлайн
Регистрация
19 Мар 2019
Сообщения
2,956
Реакции[?]
962
Поинты[?]
1K
Предыдущая тема от Dreammm - https://yougame.biz/threads/153219/
Оригинальная статья -
Пожалуйста, авторизуйтесь для просмотра ссылки.




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

В качестве напоминания, вот короткий фрагмент, который сначала выделяет одну целочисленную переменную с именем x, а затем выделяет еще две целочисленные переменные с именами y и z:

C++:
int x; // определение целочисленной переменной с именем x
int y, z; // определение двух целочисленных переменных с именами y и z
Присваивание переменных

После того как переменная определена, вы можете присвоить ей значение (в отдельном операторе) с помощью оператора =. Этот процесс называется присваиванием копии (англ. copy assignment) (или просто присваиванием) для краткости.

C++:
int width; // определение целочисленной переменной с именем width
width = 5; // присвоение копии (англ. copy assigment) значения 5 в переменную width

// переменная width теперь имеет значение 5
Присвоение копии называется так потому, что оно копирует значение в правой части оператора = в переменную в левой части оператора. Оператор = называется оператором присваивания.

Вот пример, где мы используем присваивание дважды:

C++:
#include <iostream>

int main()
{
    int width;
    width = 5; // присвоение копии значения 5 в переменную width

    // переменная width теперь имеет значение 5

    width = 7; //  изменение значения, хранящееся в переменной width, на 7

    // переменная width теперь имеет значение 7

    return 0;
}
Когда мы присваиваем переменной width значение 7, значение 5, которое было там ранее, перезаписывается. Обычные переменные могут одновременно содержать только одно значение.

Предупреждение

Одна из наиболее распространенных ошибок, которую совершают новички, заключается в том, что они путают оператор присваивания (=) с оператором равенства (==). Присваивание (=) используется для присвоения значения переменной. Равенство (==) используется для проверки того, равны ли два операнда по значению.

Копирование и прямая инициализация

Одним из недостатков присваивания является то, что оно требует по крайней мере двух операторов: один для определения переменной, а другой для присвоения значения.

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

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

C++:
int width = 5; // инициализация копирования значения 5 в переменную width
Подобно назначению копирования, это копирует значение в правой части equals в переменную, создаваемую в левой части.

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

C++:
int width( 5 ); // прямая инициализация значения 5 в переменную width
Для простых типов данных (например, целых чисел) копирование и прямая инициализация по существу одинаковы. Но для некоторых продвинутых типов прямая инициализация может работать лучше, чем инициализация копирования. До появления C++11 в большинстве случаев прямая инициализация была рекомендована вместо инициализации копирования из-за повышения производительности.


Инициализация фигурных скобок (uniform инициализация)

К сожалению, прямая инициализация на основе скобок не может использоваться для всех типов инициализации (например, инициализации объекта со списком данных). В попытке обеспечить более согласованный механизм инициализации C++11 добавил новый синтаксис, называемый инициализацией фигурных скобок (также иногда называемой uniform инициализацией), который использует фигурные скобки.

Инициализация фигурной скобки происходит в двух формах:

C++:
int width{ 5 }; // прямая инициализация фигурной скобки значения 5 в переменную width (предпочтительно)
int height = { 6 }; // инициализация копирования фигурной скобки значения 6 в переменную height
Эти две формы функционируют почти одинаково, но прямая обычно предпочтительнее.

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

C++:
int width {}; // нулевая инициализация до значения 0
Инициализация фигурных скобок имеет дополнительное преимущество в том, что она запрещает “сужающие” преобразования. Это означает, что если вы попытаетесь использовать инициализацию фигурной скобки для инициализации переменной со значением, которое она не может безопасно удерживать, компилятор выдаст предупреждение или ошибку. Например:

C++:
int width{ 4.5 }; / / ошибка: не все double значения помещаются в int
В приведенном выше фрагменте мы пытаемся присвоить число (4.5), которое имеет дробную часть (.5 Часть) к целочисленной переменной (которая может содержать только числа без дробных частей). Копирование и прямая инициализация отбросят дробную часть, что приведет к инициализации значения 4 в переменную width. Однако при инициализации фигурной скобки это приведет к тому, что компилятор выдаст ошибку (что, как правило, хорошо, потому что потеря данных редко желательна). Допускаются преобразования, которые могут быть выполнены без потенциальной потери данных.

Правило

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


(Это не викторина)
Вопрос - C++ обеспечивает инициализацию копирования, прямой и фигурной скобок, а также присваивание копий. Есть ли прямое или скобочное присваивание?

Ответ -
Нет, C++ не поддерживает синтаксис прямого или фигурного присвоения.

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

Вопрос - Когда я должен инициализировать с помощью { 0 } вместо {}?

Ответ -
Используйте явное значение инициализации, если вы действительно используете это значение.

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



Инициализируйте свои переменные

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

Для более подробного обсуждения этой темы Бьярне Страуструп (создатель C++) и Херб Саттер (эксперт по C++) сами дают эту рекомендацию
Пожалуйста, авторизуйтесь для просмотра ссылки.
.

Мы исследуем, что произойдет, если вы попытаетесь использовать переменную, которая не имеет четко определенного значения в уроке 1.6 - неинициализированные переменные и неопределенное поведение.

Правило

Инициализируйте свои переменные при создании.

Инициализация нескольких переменных

В последнем разделе мы отметили, что можно определить несколько переменных одного типа в одном операторе, разделив имена запятой:
C++:
int a, b;
Мы также отметили, что наилучшая практика заключается в том, чтобы полностью избегать этого синтаксиса. Однако, поскольку вы можете столкнуться с другим кодом, использующим этот стиль, все же полезно поговорить о нем немного больше, хотя бы для того, чтобы усилить некоторые причины, по которым вы должны избегать его.

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

C++:
int a = 5, b = 6;    // инициализация копирования
int c( 7 ), d( 8 );  // прямая инициализация
int e{ 9 }, f{ 10 }; // инициализация фигурной скобки (предпочтительно)
К сожалению, здесь есть общая ошибка, которая может возникнуть, когда программист ошибочно пытается инициализировать обе переменные с помощью одного оператора инициализации:

C++:
int a, b = 5;     // Неверно (a не инициализируется!)

int a = 5, b = 5; // Верно
В верхнем операторе переменная "а" останется неинициализированной, и компилятор может жаловаться, а может и не жаловаться. Если это не так, это отличный способ, чтобы ваша программа периодически сбоила и давала спорадические результаты. Мы еще поговорим о том, что происходит, если вы используете неинициализированные переменные в ближайшее время.

Лучший способ запомнить, что это неправильно, - рассмотреть случай прямой инициализации или инициализации скобок:

C++:
int a, b( 5 );
int c, d{ 5 };
Это делает его немного более ясным, что значение 5 используется только для инициализации переменной b или d, а не a или c.


Время викторины!

Вопрос №1 - В чем разница между инициализацией и присваиванием?
Инициализация дает переменной начальное значение в момент ее создания. Присваивание присваивает переменной значение в какой-то момент после ее создания.

Вопрос №2 - Какую форму инициализации вы должны использовать (предположим, что ваш компилятор совместим с C++11)?
Прямую инициализацую скобок.

Спасибо за прочтение :). (возможны ошибки в выборе слов между присваивание и присвоение я не силён в русском)
 
Эксперт
Статус
Оффлайн
Регистрация
24 Апр 2018
Сообщения
1,490
Реакции[?]
929
Поинты[?]
67K
Вопрос. А нахуя? Это блять даже не основы, этому в школе учат
 
Сверху Снизу