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
).
В большинстве случаев передача по значению – лучший способ принять параметры базовых типов, когда функции не нужно изменять аргумент. Передача по значению гибкая и безопасная, а в случае базовых типов – эффективная.