December 12, 2020

Способы передачи параметров в функцию

Существует 3 способа передачи параметров в функцию в С++:

  • передача по значению
  • передача по ссылке
  • передача по указателю

Передача по значению

Это означает, что значение, переданное в функцию, копируется и функция работает с копией аргумента. Рассмотрим пример:

void func(int x){
    x++;
    cout << "func: " << x << endl;
}
 
int main() {
    int n = 10;
    func(n);
    cout << "main: " << n << endl;
}

Вывод:

func: 11

main: 10

Переменная x в func изменилась на 11, при этом переменная в main осталась равна 10. Это говорит о том, что при передачи аргумента значение скопировалось.

Преимущества передачи параметров по значению:

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

Недостатки передачи параметров по значению:

  • Копирование "тяжелых" объектов может привести к значительной потери эффективности.

Вывод:

  • Передача параметров по значению эффективна в случае передачи фундаментальных типов данных (int, bool, double и т.д.)
  • Передача по значению экземпляров классов и структур не эффективна.

Передача по ссылке

Это означает, что параметр передается не по значению, а как ссылка. При этом копирование значения не происходит. Рассмотрим тот же пример, только передача параметра будет по ссылке:

void func(int &x){
    x++;
    cout << "func: " << x << endl;
}
 
int main() {
    int n = 10;
    func(n);
    cout << "main: " << n << endl;
}

Вывод:

func: 11

main: 11

Функция func изменила значение переменной n, т.к. параметр был передан по ссылке.

Преимущества передачи по ссылке:

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

Недостатки передачи по ссылке:

  • При вызове функции невозможно определить, будет аргумент изменен функцией или нет. Иногда это может привести к ошибкам.

Выводы:

  • Используйте передачу параметров по ссылке, когда передаете "тяжелые" объекты (экземпляры структур или классов), а также когда нужно, чтобы функция меняла значение параметра.
  • Не используйте передачу по ссылке при передаче фундаментальных типов и обычных массивов.

Передача по адресу

В этом случае передается адрес переменной-аргумента. Параметром функции должен быть указатель. Рассмотрим пример:

void func(int *x){
    (*x)++;
    cout << "func: " << *x << endl;
}
 
int main() {
    int n = 10;
    func(&n);
    cout << "main: " << n << endl;
}

Вывод:

func: 11

main: 11

Для того чтобы работать с параметром, функция func разыменовывает параметр x и работает с ним.

Преимущества передачи по адресу:

  • Передача по адресу позволяет функции изменить значение аргумента. Если нужно запретить изменение, необходимо использовать константный указатель.
  • Передача параметра по адресу эффективна, т.к. не происходит копирования данных.
  • Можно вернуть несколько значений из функции, используя передачу по адресу.

Недостатки передачи по адресу:

  • Необходимо проверять параметр, не является ли он нулевым, иначе попытка разыменовывания нулевого указателя приведет к ошибке.

Выводы:

  • Используйте данный тип передачи параметров при передачи обычных массивов.
  • Не используйте этот способ при передачи фундаментальных типов данных, т.к. это может привести к излишнему усложнению кода.