Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Справочник по С++.doc
Скачиваний:
49
Добавлен:
02.05.2014
Размер:
995.33 Кб
Скачать

R.8.2.3 Указатели на члены

В описании T D, в котором D имеет вид полное-имя-класса :: * список-спецификаций-cv opt D1 тип описываемого идентификатора есть "... список-спецификаций-cv указатель на член класса полное-имя-класса типа T". Например, во фрагменте class X { public: void f(int); int a; }; int X::* pmi = &X::a; void (X::* pmf)(int) = &X::f; pmi и pmf описываются как указатель на член X типа T и указатель на член X типа void(int) соответственно. Эти объекты можно использовать так: X obj; // ... obj.*pmi = 7; // присвоить 7 члену obj типа int (obj.*pmf)(7); // вызвать функцию-член obj // с параметром 7 Отметим, что указатель на член нельзя настроить на статический член класса ($$R.9.4), см. также $$R.5.5 и $$R.5.3.

R.8.2.4 Массивы

В описании T D, в котором D имеет вид D1 [ выражение-константа opt ] описывается идентификатор типа " ... массив T". Если выражение-константа присутствует ($$R.5.19), то оно должно иметь целочисленный тип и значение, большее 0. Это выражение задает число элементов массива. Если значение выражения-константы есть N, то массив имеет N элементов с индексами от 0 до N-1. Массив можно образовывать из: одного из основных типов (за исключением void), указателя, указателя на члены, класса, перечисления или из другого массива. Если подряд идут несколько спецификаций "массив ...", образуется многомерный массив, причем выражение-константа, задающее границы массива, может отсутствовать только для первого массива. Такое умолчание полезно в случае параметров функции типа массив, а также когда массив является внешним, а его определение, с которым связано резервирование памяти, находится в другом месте. Первое выражение-константа может быть пропущено и в том случае, если за описателем следует список-инициализаторов ($$R.8.4). Тогда размер массива определяется числом элементов, приведенных в инициализаторе ($$R.8.4.1). В описании float fa[17], *afp[17]; описаны массив чисел типа float и массив указателей на числа типа float, а в описании static int x3d[3][5][7]; описан статический трехмерный массив целых размера 3x5x7. Строго говоря, x3d является массивом из трех элементов, каждый из которых есть массив из пяти массивов, а каждый из последних является массивом из семи целых. В выражении допустимо появление любого из следующих выражений: x3d, x3d[i], x3d[i][j], x3d[i][j][k]. Если в выражении участвует идентификатор типа массив, то, исключая случаи операнда в операциях sizeof или & и инициализатора для ссылки ($$R.8.4.3), его тип преобразуется в указатель на первый элемент массива. Несмотря на это преобразование, массивы не являются изменяемыми адресами. Если не считать случай использования массива при описании класса ($$R.13.4.5), операция индексации определяется так, что E1[E2] совпадает с *((E1) + (E2)). С учетом правил преобразования типов для операции +, если E1 есть массив, а E2 целое, то E1[E2] указывает на E2-элемент из E1. Поэтому, несмотря на свой асиметричный вид, индексация - коммутативная операция. Аналогичное правило действует и для многомерных массивов. Если E - n-мерный массив размера ixjx...xk, то в выражении он преобразуется в указатель на (n-1)-мерный массив размера jx...xk. Если к этому указателю явно или неявно в результате индексации применяется операция *, указуемый (n-1)-мерный массив сам немедленно преобразуется в указатель. Например, рассмотрим описание int x[3][5]; Здесь описан массив из 3x5 целых. Если в выражении появляется x, то оно преобразуется в указатель на первый массив из пяти целых. Если в выражении появляется x[i], что эквивалентно *(x+i), в начале x преобразуется в указатель, как было сказано выше, затем x+i преобразуется к типу x, для чего необходимо i умножить на размер объекта, на который указывает x, т.е. на размер пяти целых. Затем происходит сложение и применяется косвенность, после чего получим массив (из пяти целых), который в свою очередь преобразуется в указатель на первое из целых. Если есть еще одна индексация, процесс повторяется, и на этот раз мы получим в результате целое. Из всего этого следует, что массивы В С++ хранятся по строкам (последний индекс изменяется быстрее всего), а значение первого индекса из описания позволяет вычислить размер памяти, необходимой для массива, однако при вычислении индексного выражения первый индекс роли не играет.