|
Программирование >> Инициализация объектов класса, структура
(a) calc( 23.4, 55.1 ); (b) count( abcda , a ); (c) sum ( vec, 43.8 ); (d) calc( 66 ); 7.3. Передача аргументов Функции используют память из стека программы. Некоторая область стека отводится функции и остается связанной с ней до окончания ее работы, по завершении которой отведенная ей память освобождается и может быть занята другой функцией. Иногда эту часть стека называют областью активации. Каждому параметру функции отводится место в данной области, причем его размер определяется типом параметра. При вызове функции память инициализируется значениями фактических аргументов. Стандартным способом передачи аргументов является копирование их значений, т.е. передача по значению. При этом способе функция не получает доступа к реальным объектам, являющихся ее аргументами. Вместо этого она получает в стеке локальные копии этих объектов. Изменение значений копий никак не отражается на значениях самих объектов. Локальные копии теряются при выходе из функции. Значения аргументов при передаче по значению не меняются. Следовательно, программист не должен заботиться о сохранении и восстановлении их значений при вызове функции. Без этого механизма любой вызов мог бы привести к нежелательному изменению аргументов, не объявленных константными явно. Передача по значению освобождает человека от лишних забот в наиболее типичной ситуации. Однако такой способ передачи аргументов может не устраивать нас в следующих случаях: передача большого объекта типа класса. Временные и пространственные расходы на размещение и копирование такого объекта могут оказаться неприемлем1ми для реальной программ:; иногда значения аргументов должны быть модифицированы внутри функции. Например, swap() должна обменять значения своих аргументов, что невозможно swap() не меняет значений своих аргументов! void swap( int vl, int v2 ) { int tmp = v2; v2 = vl; vl = tmp; при передаче по значению: swap() обменивает значения локальных копий своих аргументов. Те же переменные, что были использованы в качестве аргументов при вызове, остаются неизменными. Это можно проиллюстрировать, написав небольшую программу: #include <iostream> void swap( int, int ); int main() { int i = 10; int j = 20; cout << Перед swap():\ti: << i << \tj: << j << endl; swap( i, j ); cout << После swap():\ti: << i << \tj: << j << endl; return 0; Результат выполнения программы: Перед swap(): i: 10 j: 2 0 После swap(): i: 10 j: 2 0 Достичь желаемого можно двумя способами. Первый - объявление параметров pswap() обменивает значения объектов, адресуем указателями vl и v2 void pswap( int *vl, int *v int tmp = *v2; *v2 = *vl; *vl = tmp; указателями. Вот как будет выглядеть реализация swap() в этом случае: Функция main() тоже нуждается в модификации. Вместо передачи самих объектов необходимо передавать их адреса: pswap( &i, &j ); Теперь программа работает правильно: Перед swap(): i: 10 j: 20 После swap(): i: 20 j: 10 Альтернативой может стать объявление параметров ссылками. В данном случае реализация swap() выглядит так: rswap() обменивает значения объектов, на которые сс1лаются vl и v2 void rswap( int &vl, int &v2 ) { int tmp = v2; v2 = vl; vl = tmp; Вызов этой функции из main() аналогичен вызову первоначальной функции swap() : rswap( i, j ); Выполнив программу main() , мы снова получим верный результат. 7.3.1. Параметры-ссылки Использование ссылок в качестве параметров модифицирует стандартный механизм передачи по значению. При такой передаче функция манипулирует локальными копиями аргументов. Используя параметры-ссылки, она получает 1-значения своих аргументов и может изменять их. В каких случаях применение параметров-ссылок оправданно? Во-первых, тогда, когда без использования ссылок пришлось бы менять типы параметров на указатели (см. приведенную выше функцию swap() ). Во-вторых, при необходимости вернуть из функции несколько значений. В-третьих, для передачи большого объекта типа класса. Рассмотрим два последних случая подробнее. Как пример функции, использующей параметр-ссылку для возврата дополнительного значения, возьмем look up() , которая будет искать заданную величину в векторе целых чисел. В случае успеха look up() вернет итератор, указывающий на найденный элемент, иначе - на элемент, расположенный за конечным. Если величина содержится в векторе несколько раз, итератор будет указывать на первое вхождение. Кроме того, дополнительный параметр-ссылка occurs возвращает количество найденных элементов.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |