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,
// инициализированное
// числом 7
int* p3 = new int[100]; // размещает 100 (неинициализированных)
// чисел int
// ...
delete p1; // удаляет индивидуальный объект
delete p2;
delete[] p3; // удаляет массив
Если с помощью оператора
new
вы размещаете в памяти объекты встроенного типа, они не будут инициализированы, если не указан инициализатор. Если с помощью оператора
new
вы размещаете в памяти объекты класса, имеющего конструктор, то, если не указан инициализатор, будет вызван этот конструктор (см. раздел 17.4.4).
Оператор
delete
вызывает деструкторы каждого операнда, если они есть. Обратите внимание на то, что деструктор
может быть виртуальным (раздел A.12.3.1).
A.5.7. Операторы приведения
Существуют четыре оператора приведения к типу.
Динамическое приведение обычно используется для навигации по иерархии классов, если указатель
p
— указатель на базовый класс, а класс
D
— производный от базового класса. Если операнд
v
не относится к типу
D*
, то эта операция возвращает число
0
. Если необходимо, чтобы операция
dynamic_cast
в случае неудачи не возвращала
0
, а генерировала исключение
bad_cast
, то ее следует применять к ссылкам, а не к указателям. Динамическое приведение — единственное приведение, опирающееся на проверку типов во время выполнения программы.
Статическое приведение используется для “разумных преобразований,” т.е. если операнд v может быть результатом неявного преобразования типа
T
(см. раздел 17.8).
Оператор
reinterpret_cast
используется для реинтерпретации комбинации битов. Его переносимость не гарантируется. Фактически лучше считать, что он является вообще не переносимым. Типичным примером реинтерпретации является преобразование целого числа в указатель, чтобы получить машинный адрес в программе (см. разделы 17.8 и 25.4.1).
Приведения в стиле языка С и функциональные приведения могут выполнить любое преобразование типа, которое можно осуществить с помощью оператора
static_cast
или
reinterpret_cast
в сочетании с оператором
const_cast
.
Приведений лучше избегать. Во многих ситуациях их использование свидетельствует о плохом стиле программирования. Исключения из этого правила представлены в разделах 17.8 и 25.4.1. Приведение в стиле языка С и функциональные приведения имеют ужасное свойство: они позволяют вам не вникать в то, что именно они делают (см. раздел 27.3.4). Если вы не можете избежать явного преобразования типа, лучше используйте именованные приведения.
A.6. Инструкции
Грамматическое определение инструкций языка C++ приведено ниже (opt означает “необязательный”).