Итак, мы очень близки к аппаратному обеспечению. Для программиста это не очень удобно. В нашем распоряжении лишь несколько примитивных операций и почти нет библиотечной поддержки. Однако нам необходимо знать, как реализованы высокоуровневые средства, такие как класс vector
. Мы должны знать, как написать код на низком уровне, поскольку не всякий код может быть высокоуровневым (см. главу 25). Кроме того, для того чтобы оценить удобство и относительную надежность высокоуровневого программирования, необходимо почувствовать сложность низкоуровневого программирования. Наша цель — всегда работать на самом высоком уровне абстракции, который допускает поставленная задача и сформулированные ограничения. В этой главе, а также в главах 18–19 мы покажем, как вернуться на более комфортабельный уровень абстракции, реализовав класс vector
.
17.3.1. Оператор sizeof
int
? А указателя? Ответы на эти вопросы дает оператор sizeof
.
cout << "размер типа char" << sizeof(char) << ' '
<< sizeof ('a') << '\n';
cout << "размер типа int" << sizeof(int) << ' '
<< sizeof (2+2) << '\n';
int* p = 0;
cout << "размер типа int*" << sizeof(int*) << ' '
<< sizeof (p) << '\n';
Как видим, можно применить оператор sizeof
как к имени типа, так и к выражению; для типа оператор sizeof
возвращает размер объекта данного типа, а для выражения — размер типа его результата. Результатом оператора sizeof
является положительное целое число, а единицей измерения объема памяти является значение sizeof(char)
, которое по определению равно 1
. Как правило, тип char
занимает один байт, поэтому оператор sizeof
возвращает количество байтов.
ПОПРОБУЙТЕ
Выполните код, приведенный выше, и посмотрите на результаты. Затем расширьте этот пример для определения размера типов bool
, double
и некоторых других.
Размер одного и того же типа в разных реализациях языка С++ не обязательно совпадает. В настоящее время выражение sizeof(int)
в настольных компьютерах и ноутбуках обычно равно четырем. Поскольку в байте содержится 8 бит, это значит, что тип int
занимает 32 бита. Однако в процессорах встроенных систем тип int
занимает 16 бит, а в высокопроизводительных архитектурах размер типа int
обычно равен 64 битам.
Сколько памяти занимает объект класса vector? Попробуем выяснить.
vector
cout << "Размер объекта типа vector
<< sizeof (v) << '\n';
Результат может выглядеть так:
Размер объекта типа vector
Причины этого факта станут очевидными по мере чтения этой и следующей глав (а также раздела 19.2.1), но уже сейчас ясно, что оператор sizeof
не просто пересчитывает элементы.
17.4. Свободная память и указатели
vector
, приведенную в конце раздела 17.2. Где класс vector
находит место для хранения своих элементов? Как установить указатель elem
так, чтобы он ссылался на них? Когда начинается выполнение программы, написанной на языке С++, компилятор резервирует память для ее кода (иногда эту память называют
Язык С++ делает эту свободную память (которую также называют new
. Рассмотрим пример.
double* p = new double[4]; // размещаем 4 числа double в свободной
// памяти
Указанная выше инструкция просит систему выполнения программы разместить четыре числа типа double
в свободной памяти и вернуть указатель на первое из них. Этот указатель используется для инициализации переменной p
. Схематически это выглядит следующим образом.
Оператор new
возвращает указатель на объект, который он создал. Если оператор new
создал несколько объектов (массив), то он возвращает указатель на первый из этих массивов. Если этот объект имеет тип X
, то указатель, возвращаемый оператором new
, имеет тип X*
. Рассмотрим пример.
char* q = new double[4]; // ошибка: указатель double*
// присваивается char*