Передача аргументов в функцию
Очень важно понимать, как аргументы передаются в функцию, потому что это влияет на то, как они в конечном итоге работают. Здесь есть множество ловушек, которых следует избегать, поэтому следует рассмотреть этот механизм поближе.
Аргументы, которые специфицируются при вызове функции, обычно должны соответствовать по типу и последовательности параметрам, заданным в ее определении. Как уже говорилось, если тип аргумента, указанного при вызове функции, не соответствует типу параметра, указанному в ее определении, то там, где возможно, происходит преобразование к требуемому типу в соответствии с правилами приведения операндов. Если такое приведение невозможно, то компилятор генерирует сообщение об ошибке. Однако даже если приведение возможно и код компилируется, это может привести к потере данных (например, когда тип long приводится к short), а потому его следует избегать.
Существуют два механизма, обычно используемые C++ для передачи аргументов в функции. Первый применяется, когда параметры в определении функции специфицированы как обычные переменные (не ссылки). Это называется методом передачи по значению (pass-by-value) данных в функцию, и он будет рассмотрен первым.
Механизм передачи по значению
Когда применяется такой механизм, то переменные или константы, которые специфицируются в качестве аргументов, вообще не передаются в функцию. Вместо этого создаются копии аргументов, и эти копии используются в качестве передаваемых значений. На рис. 51 показана диаграмма применительно к функции korny_2D().
double a1 = 4.0, a2 = 8.0, a3 = 4.0; int k = 1; double result = korny_2D (a1, a2, a3, k); |
Временные копии аргументов создаются для использования в функции |
k Double result = power(value, index); |
a3 Double result = power(value, index); |
1 Double result = power(value, index); |
4 Double result = power(value, index); |
4 Double result = power(value, index); |
1 Double result = power(value, index); |
копия a3 |
копия k |
double korny_2D(double a1, double a2, double a3, int k); { …. } |
Исходные аргументы не доступны здесь, а только копии |
a2 Double result = power(value, index); |
8 Double result = power(value, index); |
8 Double result = power(value, index); |
копия a2 |
4 Double result = power(value, index); |
a1 Double result = power(value, index); |
4 Double result = power(value, index); |
копия a1 |
Рис. 51. Диаграмма передачи аргументов функции korny_2D()
Каждый раз, когда вызывается функция korny_2D(), компилятор создает копии переданных аргументов и размещает их во временном участке памяти. Во время выполнения функции все ссылки на ее параметры отображаются на эти временные копии аргументов.
Одно из последствий механизма передачи по значению состоит в том, что функция не может напрямую модифицировать переданные ей аргументы. В этом можно убедиться на следующем примере модифицируем функцию korny_2D(), так что бы она возвращала количество корней в уравнении, а сами корни поместим в заголовок в качестве аргументов.
#include <iostream>
#include <math.h>
#include<iomanip>
using namespace std;
int korny_2D(double a1,double a2,double a3,double x1,double x2);
int korny_2D(double a,double b,double c,double x1,double x2)
{
double d;
d=b*b-4.*a*c;
if(d<0.) return 0;
else
if(d==0.)
{
x1=x2=(-b+sqrt(d))/(2.*a);
return 1;
}
else
{
x1=(-b+sqrt(d))/(2.*a);
x2=(-b-sqrt(d))/(2.*a);
return 2;
}
}
int main(void)
{
double a,b,c,x1=0,x2=0;
int k;
cout<<"Vvedite kooficienty a*x^2+b*x+c+0\n";
cin>>a>>b>>c;
k=korny_2D(a,b,c,x1,x2);
cout.setf(ios::showpos);
cout<<a<<"*x^2"<<b<<"*x"<<c<<"=0\n";
switch(k)
{
case 0: cout<<"korney net\n";break;
case 1: cout<<"koren 1=n"<<x1<<"\n";break;
case 2: cout<<"2 korny\n"<<"koren 1="<<x1<<"koren 2="<<x2<<endl;break;
}
return 0;
}
Результат работы предложенной программы выглядит следующим образом (рис. 52).
Рис. 52. Результат работы программы
Описание полученных результатов
Вывод подтверждает, что, несмотря на работу функции, значения переменных x1 и x2 остались теми же, что и до работы функции (они были инициализированы 0, это необходимо, чтобы при выполнении программы среды не выдавала сообщения вида (рис. 53):
Рис. 53. Сообщение об ошибке
Если перевести это сообщение с английского языка то отладчик сообщает, что переменная x2 используется в вычислениях без предварительного присвоения значения, то есть пользователю программы сообщается, что при расчете будет использоваться «мусор», поэтому значение, скорее всего не верно.
Понятно, что механизм передачи по значению обеспечивает высокую степень защиты аргументов вызова от повреждения недобросовестной функцией, при этом функция может получить по оператору возврата только один аргумент. Иногда требуется, чтобы функция изменяла несколько значений, в этом случае используется передачи значений по указателю.