11.2 – Передача аргументов по значению
Передача по значению
По умолчанию аргументы, не являющиеся указателями, в C++ передаются по значению. Когда аргумент передается по значению, значение аргумента копируется в значение соответствующего параметра функции.
Рассмотрим следующий фрагмент:
#include <iostream>
void foo(int y)
{
std::cout << "y = " << y << '\n';
}
int main()
{
foo(5); // первый вызов
int x{ 6 };
foo(x); // второй вызов
foo(x+1); // третий вызов
return 0;
}
При первом вызове foo() аргументом является литерал 5. Когда вызывается foo(), создается переменная y, и значение 5 копируется в y. Затем, когда foo() завершается, переменная y уничтожается.
Во втором вызове foo() аргументом является переменная x. x вычисляется для получения значения 6. Когда foo() вызывается во второй раз, переменная y создается снова, и значение 6 копируется в y. Затем, когда foo() завершается, переменная y уничтожается.
В третьем вызове foo() аргументом является выражение x + 1. x + 1 вычисляется для получения значения 7, которое передается переменной y. Переменная y снова уничтожается, когда завершается foo().
Таким образом, эта программа печатает:
y = 5
y = 6
y = 7
Поскольку функции передается копия аргумента, исходный аргумент не может быть изменен функцией. Это показано в следующем примере:
#include <iostream>
void foo(int y)
{
std::cout << "y = " << y << '\n';
y = 6;
std::cout << "y = " << y << '\n';
} // y уничтожается здесь
int main()
{
int x{ 5 };
std::cout << "x = " << x << '\n';
foo(x);
std::cout << "x = " << x << '\n';
return 0;
}
Этот фрагмент выводит:
x = 5
y = 5
y = 6
x = 5
В начале main переменная x равна 5. Когда вызывается foo(), значение x (5) передается в параметр y функции foo. Внутри foo() переменной y присваивается значение 6, а затем она уничтожается. Значение x не изменилось, даже если y был изменен.
Параметры функции, передаваемые по значению, также можно сделать константными. Это позволит заручиться помощью компилятора, чтобы функция не пыталась изменить значение параметра.
Преимущества и недостатки передачи по значению
Преимущества передачи по значению:
- Аргументы, передаваемые по значению, могут быть переменными (например,
x), литералами (например, 6), выражениями (например,x + 1), структурами и классами, а также перечислителями. Другими словами, практически всё. - Аргументы никогда не изменяются вызываемой функцией, что предотвращает побочные эффекты.
Недостатки передачи по значению:
- Копирование структур и классов может значительно снизить производительность, особенно если функция вызывается много раз.
Когда использовать передачу по значению:
- При передаче переменных базовых типов данных и перечислителей, и когда функции не требуется изменять аргумент.
Когда не использовать передачу по значению:
- При передаче структур или классов (включая
std::array,std::vectorиstd::string).
В большинстве случаев передача по значению – лучший способ принять параметры базовых типов, когда функции не нужно изменять аргумент. Передача по значению гибкая и безопасная, а в случае базовых типов – эффективная.
