• Булевы преобразования. Указатели, целые числа и числа с плавающей точкой можно неявно преобразовать в значение типа
bool
. Ненулевое значение преобразовывается в значение
true
, а нуль — в значение
false
.
• Преобразования чисел с плавающей точкой в целые числа. Если число с плавающей точкой преобразуется в целое число, то его дробная часть отбрасывается. Иначе говоря, преобразование из типа с плавающей точкой в целый тип является усечением. Если усеченное значение невозможно представить с помощью целевого типа, то результат становится непредсказуемым. Преобразования целых чисел в числа с плавающей точкой являются математически корректными только в той степени, в которой это допускается аппаратным обеспечением. Если целое число невозможно точно представить как число с плавающей точкой, происходит потеря точности.
• Обычные арифметические преобразования. Эти преобразования выполняются над операндами бинарных операторов, чтобы привести их к общему типу, а затем использовать этот тип для представления результата.
1. Если один из операндов имеет тип
long double
, то другой преобразовывается в тип
long double
. В противном случае, если один из операндов имеет тип
double
, другой преобразовывается в тип
double
. В противном случае, если один из операндов имеет тип
float
, другой преобразовывается в тип
float
. В противном случае над обоими операндами целочисленного типа выполняется продвижение.
2. Если один из операндов имеет тип
unsigned long
, то другой преобразовывается в тип
unsigned long
. В противном случае, если один из операндов имеет тип
long int
, а другой —
unsigned int
, значение типа
unsigned int
преобразуется в значение типа
long int
, при условии, что тип
long int
может представить все значения типа
unsigned int
. В противном случае оба операнда преобразовываются в тип
unsigned long int
. В противном случае, если один из операндов имеет тип
long
, другой преобразовывается в тип
long
. В противном случае, если другой операнд имеет тип
unsigned
, другой преобразовывается в тип
unsigned
. В противном случае оба операнда имеют тип
int
.
Очевидно, что лучше не полагаться на слишком запутанные сочетания типов и минимизировать необходимость неявных преобразований.
A.5.2.3. Преобразования, определенные пользователем
Кроме стандартных преобразований и продвижений, программист может определить преобразования типов, определенных пользователем. Конструктор, принимающий один аргумент, определяет преобразование этого аргумента в значение своего типа. Если конструктор имеет спецификатор
explicit
(см. раздел 18.3.1), то преобразование происходит, только если программист явно потребует его выполнить. В противном случае преобразование может быть неявным.
A.5.3. Константные выражения
Константное выражение (constant expression) — это выражение, которое может быть вычислено на этапе компиляции и содержит только операнды типа
int
. (Это немного упрощенное определение, но для большинства целей оно вполне подходит.) Рассмотрим пример.
const int a = 2*3;
const int b = a+3;
Константные выражения требуются в немногих случаях, например, при вычислении границ массивов, меток разделов
case
, инициализаторов перечислений и шаблонных аргументов типа
int
. Рассмотрим пример.
int var = 7;
switch (x) {
case 77: // OK
case a+2: // OK
case var: // ошибка (var — не константное выражение)
// ...
};
A.5.4. Оператор sizeof
В выражении
sizeof(x)
аргумент
x
может быть типом или выражением. Если
x
— выражение, то значением
sizeof(x)
является размер результирующего объекта. Если
x
— тип, то значением
sizeof(x)
является размер объекта типа
x
. Размеры измеряются в байтах. По определению
sizeof(char)==1
.
A.5.5. Логические выражения
В языке C++ предусмотрены логические операторы для целочисленных типов.
Эти операторы применяются к каждому биту своих операндов, в то время как логические операторы (
&&
и
||
) трактуют число
0
как значение
false
, а все — как
true
. Определения этих операторов приведены ниже.
A.5.6. Операторы new и delete
Свободная память (динамическая память, или куча) выделяется с помощью оператора
new
, а освобождается — с помощью оператора
delete
(для индивидуальных объектов) или
delete[]
(для массива).
Если память исчерпана, то оператор
new
генерирует исключение
bad_alloc
. В случае успеха операция
new
выделяет как минимум один байт и возвращает указатель на объект, размещенный в памяти. Тип этого объекта определяется после выполнения оператора
new
. Рассмотрим пример.
int* p1 = new int; // размещает (неинициализированное) число
// типа int
int* p2 = new int(7); // размещает число типа int,