Передача параметров

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

//+------------------------------------------------------------------+
//| передача параметров по значению                                  |
//+------------------------------------------------------------------+
double FirstMethod(int i,int j)
  {
   double res;
//---
   i*=2;
   j/=2;
   res=i+j;
//---
   return(res);
  }
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   int a=14,b=8;
   Print("a и b перед вызовом:",a," ",b);
   double d=FirstMethod(a,b);
   Print("a и b после вызова:",a," ",b);
  }
//--- результат выполнения скрипта
//  a и b перед вызовом: 14 8
//  a и b после вызова: 14 8

Второй способ – передача аргумента по ссылке. В этом случае ссылка на параметр (а не его значение) передается параметру функции. Внутри функции она используется для того, чтобы обратиться к фактическому параметру, указанному в вызове. Это означает, что изменения параметра будут влиять на аргумент, использованный для вызова функции.

//+------------------------------------------------------------------+
//| передача параметров по ссылке                                    |
//+------------------------------------------------------------------+
double SecondMethod(int &i,int &j)
  {
   double res;
//---
   i*=2;
   j/=2;
   res=i+j;
//---
   return(res);
  }
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   int a=14,b=8;
   Print("a и b перед вызовом:",a," ",b);
   double d=SecondMethod(a,b);
   Print("a и b после вызова:",a," ",b);
  }
//+------------------------------------------------------------------+
//--- результат выполнения скрипта
//  a и b перед вызовом: 14 8
//  a и b после вызова: 28 4

MQL5 использует оба метода, за одним исключением: массивы, переменные типа структур и объекты классов всегда передаются по ссылке. Для того чтобы исключить изменения фактических параметров (аргументов, переданных при вызове функции) необходимо использовать спецификатор доступа const. При попытке изменить содержимое переменной, объявленной со спецификатором const, компилятор выдаст ошибку.

Примечание

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

Пример:

void OnStart()
  {
//---
   int a[]={0,1,2};
   int i=0;
 
   func(a[i],a[i++],"Первый вызов (i = "+string(i)+")");
   func(a[i++],a[i],"Второй вызов (i = "+string(i)+")");
// Результат:
// Первый вызов(i=0) : par1 = 1     par2 = 0
// Второй вызов(i=1) : par1 = 1     par2 = 1
 
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void func(int par1,int par2,string comment)
  {
   Print(comment,": par1 = ",par1,"    par2 = ",par2);
  }

При первом вызове в приведенном примере сначала переменная i участвует в конкатенации строк:

  "Первый вызов (i = "+string(i)+")"

При этом ее значение не меняется. Затем переменная i участвует в вычислении элемента массива a[i++], то есть после взятия i-го элемента массива переменная i инкрементируется. И только после этого вычисляется первый параметр с измененным значением переменной i.

Во втором вызове при вычислении всех трех параметров используется одно и тоже значение i, измененное на первом вызове функции, и только после вычисления первого параметра переменная i опять изменяется.

Смотри также

Область видимости и время жизни переменных, Перегрузка, Виртуальные функции, Полиморфизм