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

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

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

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

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

Указатель на функцию (см. раздел 27.2.5) можно только копировать и вызывать. Рассмотрим пример.

typedef void (*Handle_type)(int);

void my_handler(int);

Handle_type handle = my_handler;

handle(10); // эквивалент my_handler(10)

<p id="AutBody_Root602"><strong>A.8.2. Массивы</strong></p>

Массив (array) — это неразрывная последовательность объектов (элементов) одинакового типа, имеющая фиксированную длину.

int a[10]; // 10 целых чисел

Если массив является глобальным, то его элементы могут быть инициализированы соответствующим значением, принятым для данного типа по умолчанию. Например, значение a[7] равно 0. Если массив является локальным (переменная объявлена в функции) или создан с помощью оператора new, то элементы встроенных типов останутся неинициализированными, а элементы, имеющие пользовательский тип, будут инициализированы его конструкторами.

Имя массива неявно преобразуется в указатель на его первый элемент. Рассмотрим пример.

int* p = a; // указатель p ссылается на элемент a[0]

Массив или указатель на элемент массива может индексироваться с помощью оператора []. Рассмотрим пример.

a[7] = 9;

int xx = p[6];

Элементы массива нумеруются начиная с нуля (разделы 18.5).

Диапазон индексов массива не проверяется. Кроме того, поскольку они часто передаются с помощью указателей, информация, необходимая для проверки диапазона, передается пользователям ненадежным способом. Рекомендуем использовать класс vector. Размер массива — это сумма размеров его элементов. Рассмотрим пример.

int a[max]; // sizeof(a) == sizeof(int)*max

Можно определить и использовать массив массивов (двумерный массив), массив массивов массивов (многомерный массив) и т.д. Рассмотрим пример.

double da[100][200][300]; // 300 элементов типа, состоящего из

da[7][9][11] = 0;

Нетривиальное использование многомерных массивов — тонкое и уязвимое для ошибок дело (см. раздел 24.4). Если у вас есть выбор, следует предпочесть класс Matrix (как в главе 24). 

<p id="AutBody_Root603"><strong>A.8.3. Ссылки</strong></p>

Ссылка (reference) — это синоним (alias), т.е. альтернативное имя объекта.

int a = 7;

int& r = a;

r = 8; // переменная a становится равной 8

Ссылки часто используются в качестве параметров функций, чтобы предотвратить копирование.

void f(const string& s);

// ...

f("эту строку слишком дорого копировать, \\

   поэтому используется ссылка");

См. разделы 8.5.4–8.5.6.

<p id="AutBody_Root604"><strong>A.9. Функции</strong></p>

Функция (function) — это именованный фрагмент кода, получающий (возможно, пустой) набор аргументов и (необязательно) возвращающий значение. Функция объявляется с помощью указания типа возвращаемого значения, за которым следует ее имя и список параметров.

char f(string, int);

Итак, f — это функция, принимающая объекты типа string и int и возвращающая объект типа char. Если функция должна быть просто объявлена, но не определена, то ее объявление завершается точкой с запятой. Если функция должна быть определена, то за объявлением аргументов следует тело функции.

char f(string s, int i) { return s[i]; }

Телом функции должен быть блок (см. раздел 8.2) или блок try (см. раздел 5.6.3).

Функция, в объявлении которой указано, что она возвращает какое-то значение, должна его возвращать (используя оператор return).

char f(string s, int i) { char c = s[i]; } // ошибка: ничего

                                           // не возвращается

Функция main представляет собой странное исключение из этого правила (см. раздел A.1.2). За исключением функции main, если не хотите возвращать значение, то поставьте перед именем функции ключевое слово void. Другими словами, используйте слово void как тип возвращаемого значения.

void increment(int& x) { ++x; } // OK: возвращать значение

Перейти на страницу:

Похожие книги

97 этюдов для архитекторов программных систем
97 этюдов для архитекторов программных систем

Успешная карьера архитектора программного обеспечения требует хорошего владения как технической, так и деловой сторонами вопросов, связанных с проектированием архитектуры. В этой необычной книге ведущие архитекторы ПО со всего света обсуждают важные принципы разработки, выходящие далеко за пределы чисто технических вопросов.?Архитектор ПО выполняет роль посредника между командой разработчиков и бизнес-руководством компании, поэтому чтобы добиться успеха в этой профессии, необходимо не только овладеть различными технологиями, но и обеспечить работу над проектом в соответствии с бизнес-целями. В книге более 50 архитекторов рассказывают о том, что считают самым важным в своей работе, дают советы, как организовать общение с другими участниками проекта, как снизить сложность архитектуры, как оказывать поддержку разработчикам. Они щедро делятся множеством полезных идей и приемов, которые вынесли из своего многолетнего опыта. Авторы надеются, что книга станет источником вдохновения и руководством к действию для многих профессиональных программистов.

Билл де Ора , Майкл Хайгард , Нил Форд

Программирование, программы, базы данных / Базы данных / Программирование / Книги по IT