Упражнение 4.9. Объясните поведение следующего условия оператора if
:
const char *cp = "Hello World";
if (cp && *cp)
Упражнение 4.10. Напишите условие цикла while
, который читал бы целые числа со стандартного устройства ввода, пока во вводе не встретится значение 42
.
Упражнение 4.11. Напишите выражение, проверяющее четыре значения а
, b
, с
и d
и являющееся истинным, если значение а
больше b
, которое больше c
, которое больше d
.
Упражнение 4.12. С учетом того, что i
, j
и k
имеют тип int
, объясните значение выражения i != j < k
.
4.4. Операторы присвоения
Левым операндом оператора присвоения должно быть допускающее изменение l-значение. Ниже приведено несколько примеров недопустимых попыток присвоения.
int i = 0, j = 0, k = 0; //
const int ci = i; //
1024 = k; //
i + j = k; //
ci = k; //
Результат присвоения, левый операнд, является l-значением. Тип результата совпадает с типом левого операнда. Если типы левого и правого операндов отличаются, тип правого операнда преобразуется в тип левого.
k = 0; //
k = 3.14159; //
k = {3.14}; //
vector
vi = {0,1,2,3,4,5,6,7,8,9}; //
//
Если левый операнд имеет встроенный тип, список инициализации может содержать максимум одно значение, и это значение не должно требовать
Для типов классов происходящее зависит от подробностей класса. В случае вектора шаблон vector
определяет собственную версию оператора присвоения, позволяющего использовать список инициализации. Этот оператор заменяет элементы вектора с левой стороны элементами списка с правой.
Независимо от типа левого операнда список инициализации может быть пуст. В данном случае компилятор создает инициализированный значением по умолчанию (см. раздел 3.3.1) временный объект и присваивает это значение левому операнду.
В отличие от других парных операторов, присвоение имеет правосторонний порядок:
int ival, jval;
ival = jval = 0; //
Поскольку присвоение имеет правосторонний порядок, его крайняя правая часть, jval = 0
, является правым операндом крайнего левого оператора присвоения. Поскольку присвоение возвращает свой левый операнд, результат крайнего правого присвоения (т.е. jval
) присваивается переменной ival
.
Каждый объект в множественном операторе присвоения должен иметь тип, совпадающий с типом соседа справа, или допускать преобразование в него (раздел 4.11):
int ival, *pval; //
ival = pval = 0; //
//
string s1, s2;
s1 = s2 = "OK"; //
Первое присвоение некорректно, поскольку объекты ival
и pval
имеют разные типы и не существует преобразования типа int*
(pval
) в тип int
(ival
). Оно некорректно, несмотря на то, что значение нуль может быть присвоено любому объекту.
Второе присвоение, напротив, вполне допустимо. Строковый литерал преобразуется в значение типа string
, которое и присваивается переменной s2
типа string
. Результат этого присвоения — строка s2
— имеет тот же тип, что и строка s1
.