Чтение онлайн

ЖАНРЫ

Программирование. Принципы и практика использования C++ Исправленное издание
Шрифт:

if (x==terminator) break; // выход из цикла while

v.push_back(x);

}

for (int i = 0; i<v.size && i<n; ++i) {

if (v[i]==*p)

return p;

else

++p;

}

return 0;

}

A.7. Объявления

Объявление (declaration)

состоит из трех частей:

• имя объявляемой сущности;

• тип объявляемой сущности;

• начальное значение объявляемой сущности (во многих случаях необязательное).

Мы можем объявлять следующие сущности:

• объекты встроенных типов и типов, определенных пользователем (раздел A.8);

• типы, определенные пользователем (классы и перечисления) (разделы A.10–А.11, глава 9);

• шаблоны (шаблонные классы и функции) (раздел A.13);

• альтернативные имена (раздел A.16);

• пространства имен (разделы A.15 и 8.7);

• функции (включая функции-члены и операторы) (раздел A.9, глава 8);

• перечисления (значения перечислений) (разделы A.11 и 9.5);

• макросы (разделы A.17.2 и 27.8).

A.7.1. Определения

Определение с инициализацией, резервирующее область памяти или как-то иначе поставляющую компилятору всю информацию, необходимую для использования имени в программе, называется определением (definition). Каждый тип, объект и функция в программе должны иметь только одно определение. Рассмотрим примеры.

double f; // объявление

double f { /* ... */ }; // также определение

extern const int x; // объявление

int y; // также определение

int z = 10; // определение с явной инициализацией

Константы должны быть инициализированы. Для этого используется инициализатор, если константа не объявлена с помощью ключевого слова extern (в таком случае инициализатор вместе с определением должны быть расположены в другом месте) или если константа не имеет тип, имеющий конструктор по умолчанию (раздел A.12.3). Константные члены класса должны инициализироваться в каждом конструкторе с помощью инициализатора (раздел A.12.3).

A.8. Встроенные типы

Язык C++ имеет много фундаментальных типов и типов, составленных из фундаментальных типов с помощью модификаторов.

Здесь

T
означает “некий тип”, поэтому существуют варианты
long unsigned int
,
long double
,
unsigned char
и
const char*
(указатель на константный символ
char
). Однако эта система не совсем полная; например, в ней нет типа
short double
(его роль играет тип
float
); типа
signed bool
(совершенно бессмысленного); типа
short long int
(это было бы лишним) и типа
long long long long int
. Некоторые компиляторы в ожидании стандарта C++0x допускают тип
long long int
(читается как “очень длинный целый тип ”). Гарантируется, что тип
long long
содержит не менее 64 бит.

Типы с плавающей точкой (floating-point types) — это типы

float
,
double
и
long double
. Они являются приближением действительных чисел в языке С++.

Целочисленные типы (integer types), иногда называемые интегральными (integral), — это типы

bool
,
char
,
short
,
int
,
long
и (в языке C++0x)
long long
, а также их варианты без знака. Обратите внимание на то, что тип или значения перечислений часто можно использовать вместо целочисленного типа или значения.

Размеры встроенных типов обсуждались в разделах 3.8, 17.3.1 и 25.5.1; указатели и массивы — в главах 17 и 18; ссылки — в разделах 8.5.4–8.5.6.

A.8.1. Указатели

Указатель (pointer) — это адрес объекта или функции. Указатели хранятся в переменных указательных типов. Корректный указатель на объект содержит адрес этого объекта.

int x = 7;

int* pi = &x; // указатель pi ссылается на объект x

int xx = *pi; // *pi — это значение объекта,

// на который ссылается указатель pi, т.е. 7

Некорректный указатель — это указатель, не содержащий указателя ни на один объект.

int* pi2; // неинициализированный

*pi2 = 7; // неопределенное поведение

pi2 = 0; // нулевой указатель (указатель pi2 остается некорректным)

*pi2 = 7; // неопределенное поведение

pi2 = new int(7); // теперь указатель pi2 становится корректным

int xxx = *pi2; // отлично: переменная xxx становится равной 7

Мы хотим, чтобы все некорректные указатели были нулевыми (

0
), поэтому можем провести проверку.

if (p2 == 0) { // "если указатель некорректный"

// не используйте значение *p2

}

Или еще проще:

if (p2) { // "если указатель корректный"

// используйте значение *p2

}

См. разделы 17.4 и 18.5.4.

Перечислим операции над указателями на объекты (не

void
). Операции сравнения
<
,
<=
,
>
,
>+
можно применять только к указателям одного и того же типа внутри одного и того же объекта или массива.

Подчеркнем, что операции арифметики указателей (например,

++p
и
p+=7
) могут применяться только к указателям, ссылающимся на элементы массива, а эффект разыменования указателя, ссылающегося на область памяти за пределами массива, не определен (и, скорее всего, не сможет быть проверен компилятором или системой выполнения программ).

Только операции над указателем типа

void*
являются копированием (присваиванием или инициализацией) и приведением (преобразованием типа).

Поделиться с друзьями: