Здесь мы рассмотрим вопросы передачи нескольких значений в функцию и из
нее.
Начнем с классического примера. Предположим, что мы хотим, чтобы переменные x и y одного типа обменялись своими значениями с помощью функции, которую мы назовем interchange(). Чтобы было ясно, какая переменная принадлежит функции main(), а какая - функции interchange(), мы будем использовать переменные x и y в первой из них, и u и v - во второй.
#include <iostream.h> void interchange (int u,int v) { int temp=u; u = v; v = temp; } /* ------------- */ void main () { int x=5,y=10; /* --------------------------------------- */ cout << "Вначале x = " << x << " и y = " << y << endl; interchange (x,y); cout << "Теперь x = " << x << " и y = " << y << endl; }
Результат работы программы:
Вначале x = 5 и y = 10. Теперь x = 5 и y = 10.
Поместим в функцию interchange() промежуточную печать, чтобы попытаться понять причину ошибки:
void interchange (int u,int v) { cout << "Вначале u=" << u << " и v=" << v << endl; int temp=u; u = v; v = temp; cout << "Теперь u=" << u << " и v=" << v << endl; }
Результат работы программы:
Вначале x=5 и y=10. Вначале u=5 и v=10. Теперь u=10 и x=5. Теперь x=5 и y=10.
Отсюда видно, что функция interchange() действительно осуществляет обмен значениями между переменными u и v. Проблема состоит в передаче результатов обратно в функцию main()!
Мы могли бы, конечно, воспользоваться оператором return u, но с его помощью в вызывающую программу можно передать только одно значение.
Возникает вопрос: как быть, если необходимо вернуть несколько значений? Этого можно достичь несколькими способами, "классическим" среди которых является использование переменных ссылочного типа.
Внесем изменения в пример:
#include <iostream.h> void interchange (int *u,int *v) { int p; p = *u; *u = *v; *v = p; } /* ------------- */ void main () { int x = 1, y = 3; cout << "Имели... x= " << x << " y = " << y << endl; //Обращение к функции (передаются адреса переменных). interchange (&x,&y); cout << "Получили... x= " << x << " y = " << y << endl; }
Результат работы программы:
Имели... x = 1 y = 3 Получили... x = 3 y = 1
Комментарии к примеру. При вызове функции interchange() с аргументами &x,&y вместо передачи значений x и y мы передаем их адреса. Естественно, что формальные аргументы u и v, имеющиеся в определении функции interchange() должны быть описаны как указатели.
Поскольку x и y - переменные целого типа, то u и v должны быть указателями на переменные целого типа.
Оператор описания int p; используется с целью резервирования памяти. Мы хотим поместить значение переменной x в переменную p, поэтому пишем: p = *u;. Вспомните, что значение переменной u - это &x, поэтому переменная u ссылается на x. Это означает, что операция *u дает значение x, которое как раз нам и требуется. Аналогично, оператор *u=*v; соответствует оператору x=y;. Попытайтесь самостоятельно описать назначение оператора *v=p;.
Подведем итоги. Нам требовалась функция, которая могла бы поменять местами значения переменных x и y. Используя указатели и операцию *, функция смогла извлечь величины, помещенные в соответствующие ячейки памяти, и поменять их местами.
Вообще говоря, при вызове функции информация о переменной может передаваться функции в двух видах.
Если мы используем форму обращения function1(x), то происходит передача значения переменной x. Эта форма обращения требует, чтобы определение функции включало в себя формальный аргумент того же типа, что и x: function1 (int num).
Если мы используем форму обращения function2(&x) то происходит передача адреса переменной x. А эта форма обращения требует, чтобы определение функции включало в себя формальный аргумент, являющийся указателем на объект соответствующего типа: function2(int *x).
Пользуйтесь первой формой, если входные значения необходимы функции для некоторых вычислений или действий, и второй формой, если функция должна изменять значения переменных в вызывающей функции.
На следующем шаге мы продолжим рассмотрение способов, позволяющих
передавать несколько
значений, в частности, поговорим о ссылках.