Справочное руководство по C++ - Бьярн Страустрап
Шрифт:
Интервал:
Закладка:
R.5.2.2 Вызов функции
Вызов функции является постфиксным выражением, за которым следует, возможно пустой, список выражений в скобках, разделенных запятой. Эти выражения образуют фактические параметры функции. Постфиксное выражение должно иметь тип "функция, возвращающая T", "указатель на функцию, возвращающую T" или "ссылка на функцию, возвращающую T", а результат операции вызова имеет тип "T".
При вызове функции происходит инициализация каждого формального параметра (§R.8.4.3, §R.12.8, $$r.12.1) фактическим параметром. Производятся стандартные (§R.4) и заданные пользователем (§R.12.3) преобразования типа. В функции может изменяться значения непостоянных формальных параметров, но эти изменения не могут повлиять на значения фактических параметров, кроме того случая, когда формальный параметр имеет тип ссылки без спецификации const (§R.8.2.2). Если формальный параметр имеет тип ссылки при необходимости может создаваться временная переменная (§R.7.1.6, §R.2.5,§R.2.5.4,§R.8.2.4, §R.12.2). Добавим, что возможно изменение непостоянных объектов с помощью параметров-указателей.
Функцию можно описать таким образом, что она сможет использовать меньшее число параметров (определив параметры по умолчанию §R.8.2.6) или большее число параметров (с помощью эллипсиса … §R.8.2.5), чем было указано при определении функции (§R.8.3).
Функцию можно вызвать только, если описание ее доступно в той области видимости, где происходит вызов. Отсюда следует, всякий формальный параметр, соответствующий некоторому фактическому параметру, должен быть доступен, если не считать эллипсис (…).
Перед вызовом всякий фактический параметр типа float, для которого нет формального параметра, преобразуется к типу double, а типа char, short, перечисления или битовое поле, для которого нет формального параметра, преобразуется к типу int или unsigned согласно стандартным преобразованиям целочисленных (§R.4.1). Объект, являющийся классом и не имеющий описания формального параметра, передается при вызове как структура данных.
Объект, являющийся классом и имеющий описание формального параметра передается с помощью инициализации формального параметра фактическим параметром, которая происходит перед выполнением функции посредством вызова конструктора (§R.12.2, §R.12.8).
Порядок вычислений параметров неопределен и учтите, что он может быть различен у разных трансляторов. Все побочные эффекты выражений фактических параметров могут происходить перед началом выполнения функции. Порядок вычисления постфиксных выражений и списка выражений параметров неопределен.
Допустимы рекурсивные вызовы.
Операция вызова функции порождает адрес только, если тип результата есть адрес.
R.5.2.3 Явные преобразования типа
Конструкция имя-простого-типа (§R.7.1.6), за которой следует список-выражений в скобках образует значение указанного типа с учетом списка выражений. Если список выражений содержит более одного значения, тип должен быть классом с конструктором, описанным соответствующим образом (§R.8.4, §R.12.1).
Конструкция имя-простого-типа (§R.7.1.6), за которой следует пара скобок (пустая), образует значение указанного типа. Если тип является классом с конструктором, описанным соответствующим образом, будет вызван этот конструктор, в противном случае результатом будет неопределенное значение указанного типа, см. так же (§R.5.4).
R.5.2.4 Доступ к члену класса
Постфиксное выражение, за которым следует точка (.) и имя, является постфиксным выражением. Первое выражение должно быть объектом типа класс, а имя должно быть именем члена этого класса. Результатом будет поименованный член объекта и он будет адресом, если член является адресом.
Постфиксное выражение, за которым следует стрелка (-›) и имя, является постфиксным выражением. Первое выражение должно быть указателем на объект типа класс, а имя должно быть именем члена этого класса. Результатом будет поименованный член объекта, на который настроен указатель и он будет адресом, если член является адресом. Значит выражение E1-›MOS тоже самое, что (*E1).MOS.
Обратите внимание, что "объекты типа класс" могут быть структурами (§R.9.2) или объединениями (§R.9.5). Классы обсуждаются в §R.9.
R.5.2.5 Инкремент и декремент
Значение, получаемое в результате применения постфиксной операции ++, есть значение операнда. Операнд должен быть изменяемым адресом. Тип операнда должен быть арифметический или тип указателя. После выборки результата (для дальнейшего использования) объект увеличивается на 1. Тип результата совпадает с типом операнда, но не является адресом (см. так же §R.5.7 и §R.5.17).
Постфиксная операция -- сводится к операции декремента (уменьшение на 1) и аналогична операции ++.
R.5.3 Унарные операции
Выражения с унарными операциями выполняются справа налево.
унарное-выражение:
постфиксное-выражение
++ унарное выражение
-- унарное выражение
унарная-операция выражение-приведения
sizeof унарная-операция
sizeof (имя-типа)
выражение-размещения
выражение-освобождения
унарная-операция: один из
* & + - ! ~
Унарная операция * означает косвенность: выражение должно быть указателем, а результат является адресом, ссылающимся на объект, на который указывает выражение. Если тип выражения есть "указатель на T", то тип результата будет "T".
Результатом унарной операции & будет указатель на ее операнд. Операнд должен быть функцией или адресом или конструкцией уточненное-имя. Для первых двух случаев, если тип выражения есть "T", то тип результата будет "указатель на T". В частности, адрес объекта типа const T имеет тип const T*, тоже верно для volatile. Для случая уточненное имя если член класса "C" не является статическим и имеет тип "T", то тип результата операции будет "указатель на член C типа T". Для статических членов типа T результатом будет обычный "указатель на T". Адрес перегруженной функции (§R.13) можно брать только при инициализации или присваивании, в котором левая часть однозначно определяет какая версия перегруженной функции имеется ввиду ($R13.3).
Операнд унарной операции + должен быть арифметического типа или типа указатель и результатом будет значение операнда. Для целочисленных операндов производится стандартное преобразование целочисленных. Тип результата есть тип преобразованного операнда.
Операнд унарной операции - должен иметь арифметический тип и результатом будет изменение знака операнда. Для целочисленных операндов выполняется стандартное преобразование целочисленных.
Операция для беззнаковых величин выполняется с помощью вычитания значения операнда из 2n, где n число битов в представлении преобразованного операнда. Тип результата есть преобразованного операнда.
Операнд операции логического отрицания ! должен иметь арифметический тип или быть указателем, результат равен 1, если значение операнда есть 0, и равен 0, если операнд не равен 0. Тип результата есть int.
Операнд операции ~ должен иметь целочисленный тип, результатом будет обращение двоичного представления операнда. Выполняются стандартные преобразования целочисленных. Тип результата есть тип преобразованного операнда.
R.5.3.1 Инкремент и декремент
Операнд префиксной операции ++ увеличивается на 1. Операнд должен быть изменяемым адресом. Тип операнда должен быть арифметическим или указателем. Результатом является новое значение операнда, оно считается адресом. Выражение ++x эквивалентно x+=1. Для уточнения преобразований можно обратиться к описанию сложения (§R.5.7) и операций присваивания (§R.5.17).
Префиксная операция -- сводится к уменьшению на 1 и выполняется аналогично префиксной операции ++.
R.5.3.2 Операция sizeof
Операция sizeof вычисляет размер своего операнда в байтах. Операнд должен быть или выражением, которое не вычисляется, или именем типа в скобках. Операцию sizeof нельзя применять к функции, битовому полю, неопределенному классу, типу void или к массиву с неуказанными границами индексов. Байт никак не определяется языком, кроме как результата операции sizeof, именно sizeof(char) есть 1.
Если операция применяется к ссылке, результатом будет размер объекта, на который настроена ссылка. Если она применяется к классу, результатом будет размер объекта этого класса в байтах с учетом всех дополнительных байтов, которые потребуется для размещения такого объекта в массиве. Размер любого класса или объекта класса больше нуля. В случае массива операция выдает полное число байтов в массиве. Отсюда следует, что размер массива из n элементов равен размеру элемента, умноженному на n.