Russian Belarusian English German Japanese Ukrainian
  • Главная
  • Передача параметров в функции по значению и по ссылке

3.35

Список параметров, передаваемый в функции, как было показано в предыдущем разделе, состоит из имен параметров и указаний на их тип. Например, в заголовке:

double FSum(double X1, double X2, int A)

указано три параметра X1, X2, А и определены их типы. Вызов такой процедуры может иметь вид:

Pr(Y, Х2, 5);

Это только один из способов передачи параметров в процедуру, называемый передачей по значению. Работает он так. В момент вызова функции в памяти создаются временные переменные с именами X1, Х2, А, и в них копируются значения аргументов Y, Х2 и константы 5. На этом связь между аргументами и переменными X1, Х2, А разрывается. Вы можете изменять внутри процедуры значения X1, Х2 и А, но это никак не отразится на значениях аргументов. Аргументы при этом надежно защищены от непреднамеренного изменения своих значений вызванной функцией. Это предотвращает случайные побочные эффекты, которые так сильно мешают иногда созданию корректного и надежного программного обеспечения.

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

Возможен и другой способ передачи параметров вызов по ссылке. В случае вызова по ссылке оператор вызова дает вызываемой функции возможность прямого доступа к передаваемым данным, а также возможность изменения этих данных. Вызов по ссылке хорош в смысле производительности, потому что он исключает накладные расходы на копирование больших объемов данных; в го же время он может ослабить защищенность, потому что вызываемая функция может испортить передаваемые в нее данные.
Вызов по ссылке можно осуществить двумя способами: с помощью ссылочных параметров и с помощью указателей. Ссылочный параметр - это псевдоним соответствующего аргумента. Чтобы показать, что параметр функции передан по ссылке, после типа параметра в прототипе функции ставится символ амперсанда (&); такое же обозначение используется в списке типов параметров в заголовке функции. Перед амперсандом и после него могут вставляться пробельные символы. Например, идентичные объявления:

int &count
int & count
int& count

в списке параметров заголовка функции могут читаться как «count является ссылкой на int». В вызове такой функции достаточно указать имя переменной и она будет передана по ссылке. Реально в функцию передается не сама переменная, а ее адрес, полученный операцией адресации (&). Тогда упоминание в теле вызываемой функции переменной по имени ее параметра в действительности является обращением к исходной переменной в вызывающей функции и эта исходная переменная может быть изменена непосредственно вызываемой функцией. Например:

void square(int&); // Прототип функции вычисления квадрата
void square(int &a) //Заголовок функции
{
a*= a;// Изменение значения параметра
}

Вызываться подобная функция может обычным способом передачей в нее имени аргумента. Например:

int x1 = 2;
square(x1);

В результате подобного вызова переменная x1 получит значение 4.

Поскольку ссылочные параметры упоминаются в теле вызываемой функции просто по имени, программист может нечаянно принять ссылочный параметр за параметр, переданный по значению. Это может привести к неприятным ошибкам, если исходные значения переменных изменяются вызывающей функцией.

Альтернативной формой передачи параметра по ссылке является использование указателей. Тогда адрес переменной передается в функцию не операцией адресации (&), а операцией косвенной адресации (*). В списке параметров подобной функции перед именем переменной указывается символ "*", свидетельствуя о том, что передается не сама переменная, а указатель на нее. В теле функции тоже перед именем параметра ставится символ операции разыменования "*", чтобы получить доступ через указатель к значению переменной. А при вызове функции в нее в качестве аргумента должна передаваться не сама переменная, а ее адрес, получаемый с помощью операции адресации &.

Приведем пример той же рассмотренной ранее функции square, но с передачей параметра по ссылке с помощью указателя:

void square(int *); // Прототип функции вычисления квадрата
void square(int *а) //Заголовок функции {
*а *= *а; // Изменение значения параметра
}

Вызов подобной функции может осуществляться, например, следующим образом:

int x1 = 2;
square(&x1);

Если заметили ошибку, выделите фрагмент текста и нажмите Ctrl+Enter

Добавить комментарий


Поиск по сайту