Я рекомендовал (см., Например, здесь ), что если вы хотите создать копию параметра для функции, вы должны передать ее по значению, чтобы сделать копиюавтоматически в списке инициализации.
Т.е. вместо записи
void some_function_ref(Some_class const& input)
{
Some_class copy_of_input(input);
// Do something with copy_of_input
}
мы должны написать
void some_function_val(Some_class input)
{
// Do something with input
}
.В C ++ 11 для этого есть изящная причина: второй случай будет выбирать между вызовом конструктора копирования или конструктора перемещения в зависимости от того, передан ли ему lvalue или rvalue, тогда как в первом случае всегда вызывается конструктор копирования.
Например, если мы вызываем
some_function_ref(function_that_returns_some_class())
, тогда программа создаст временное хранилище для хранения возвращаемого значения function_that_returns_some_class
, а затем сделает копию этого временного объекта внутри функции.Принимая во внимание, что если мы вызовем
some_function_val(function_that_returns_some_class())
, то программа создаст временное значение, как и раньше, но теперь переместит временное значение в функцию и будет использовать это значение для внутреннего использования.Мы избежали ненужной копии.
Тем не менее, some_function_ref
имеет свои преимущества: если мы хотим упростить отладку нашего кода, то может быть полезно увидеть значение input
, которое былоперешел в функцию.Если some_function
было передано lvalue, то мы можем увидеть это значение, проверив значение переменной во включающей области видимости.Однако, если ему было передано значение r, у нас может не быть возможности увидеть, что это такое.
Конечно, для этого есть причина: если функция была вызвана с помощью значения r, тогда some_function_val
будет использовать конструктор перемещения для временного объекта, что означает, что его старое значение больше не существует!С точки зрения оптимизации это замечательно, так как мы избежали лишней копии.С точки зрения отладки, это не так хорошо.
Что было бы действительно хорошо, если бы мы могли видеть исходное значение input
в неоптимизированной отладочной сборке кода, но переместить значение воптимизированная сборка релиза.По этой причине у меня будет соблазн использовать первую версию (some_function_ref
), исходя из предположения, что компилятор оптимизирует копию и вызовет вместо этого конструктор перемещения, если я включил оптимизацию, эффективно преобразовав some_function_ref
вsome_function_val
.
Это разумное предположение?Является ли компилятор (например, gcc, clang и т. Д.) Достаточно умным, чтобы понять, что input
используется только для копирования и оптимизации some_function_ref
, чтобы сделать то же самое, что и some_function_val
?