Передача параметров по значению и по ссылке

Прежде чем приступать к рассмотрению темы передачи параметров, читателям следует запомнить следующее: в разделенном запятыми списке нельзя определять несколько параметров одного и того же типа, как это можно было делать в Delphi:

procedure ParamSample(I, J, К: Integer; A, B: Double);

begin

end;

В C++ все параметры должны быть полностью определены путем указания типа данных, а затем имени параметра:

void param_sample(int i, int j, int k, double a, double b)

{

}

 

При объявлении списка параметров, как это было сделано ранее (вначале типа данных, а затем имени параметра), вы объявляете параметры, которые принимают копию значения аргумента. (Аргумент — это все, что передается параметру функции, например, константа или переменная.) В C++ параметры-значения работают совершенно так же, как параметры-значения Delphi — параметр принимает только копию значения. Значение параметра может свободно изменяться в теле функции, но, независимо от выполняемых с ним действий, изменения не отражаются на внешней среде функции.

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

Для объявления параметра-ссылки (в Delphi его называют параметром-переменной) необходимо использовать операцию ссылки (&) после типа данных, между типом данных и именем параметра или перед именем параметра — выбор конкретной формы не имеет значения. Синтаксис объявления параметра-ссылки представлен ниже (следующие объявления различаются только позицией операции ссылки):

возвращаемый_тип имя_функции{тип_данных& имя_параметра);

возвращаемый_тип имя_функции{тип_данных & имя__параметра) ;

возвращаемый_тип имя_функции(тип__данных &имя_параметра) ;

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

Листинг 3.5. Передача параметров по значению и по ссылке

#include <iostream>

#include <conio.h>

using namespace std;

 

void my_abs(int i) // передача по значению, не работает

{

if (i < 0)

i = -i;

}

void my_abs_ref(int& i) // передача по ссылке, работает правильно

{

if (i < 0)

i = -i;

}

// обычная передача по значению, поскольку мы не изменяем

// значение переменной num

void show_int(int num)

{

cout << num << endl;

}

 

int main(int argc, char* argv[])

{

int test = -5;

my_abs(test) ;

show_int(test); // -5, не верно

my_abs_ref(test) ;

show_int(test); // 5, все правильно, поскольку значение test

// было передано по ссылке getch(); return 0;

 

getch();

return 0;

}

Прототипы функций

В C++ и в Delphi все функции (и процедуры) должны быть объявлены до их использования. До сих пор мы решали эту проблему, объявляя все функции до главной функции, что автоматически делало их пригодными для использования в программе. Однако это отнюдь не лучший способ объявления функций в C++. Предпочтительный способ объявления функций, который предоставляет компилятору возможность выполнять более строгую проверку типов — их объявление после главной функции. Но при таком объявлении функцию нельзя использовать в главной функции, не располагая прототипом функции.

Прототип функции аналогичен упреждающему объявлению в Delphi. В C++ прототип функции — это заголовок функции, за которым следует символ точки с запятой:

возвращаемый_тип имя_функции(список_параметров);

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