Насколько я знаю, в C ++ 11 универсальная ссылка всегда должна использоваться с std::forward
, но я не уверен, какая проблема может возникнуть, если std::forward
не используется
template <T>
void f(T&& x);
{
// What if x is used without std::forward<T>(x) ?
}
Не могли бы вы привести примеры проблем, которые могут возникнуть в этой ситуации?
Есть нет такого правила в всегда использование std::forward
с универсальные ссылки. Наоборот, это может быть опасно для использования std::forward
повсюду в функциях с универсальные ссылки. Взгляните на следующий пример:
template <typename T>
auto make_pair(T&& t)
{
return std::make_tuple(std::forward<T>(t), std::forward<T>(t)); // BAD
}
Если вы вызываете эту функцию с make_pair(std::string{"foobar"})
результат нелогичен, потому что вы перемещаетесь с одного и того же объекта дважды.
Обновить: Вот еще один пример, чтобы показать, что это действительно имеет смысл использовать универсальные ссылки без идеальная пересылка:
template <typename Range, typename Action>
void foreach(Range&& range, Action&& action)
{
using std::begin;
using std::end;
for (auto p = begin(range), q = end(range); p != q; ++p) {
action(*p);
}
}
std::forward
за спектр или для действие.Скажем f
называется так:
f(someType{});
Если тело f
выполняет какую-то операцию на x
foo(x);
и есть две перегрузки для foo
void foo(someType const&);
void foo(someType&&);
без использования std::forward
, как x
является lvalue, следующая перегрузка называется
void foo(someType const&);
что может стоить вам потенциальной оптимизации.
С помощью
foo(std::forward<T>(x));
обеспечивает правильную перегрузку foo
выбран.
Вещи с именем являются lvalues. Это означает, что в теле функции, t
это значение. Не имеет значения, является ли универсальная ссылка константой lvalue или ссылкой rvalue. Если это имя, это lvalue.
Таким образом, если вы передадите этот аргумент напрямую, вы передадите lvalue.
В ситуации, когда вы хотите просто передать непрозрачный аргумент другой функции, вы хотите передать его в точности как есть. Если это было lvalue, вы хотите передать его как lvalue; если это было значение, вы хотите передать значение. Как объяснено, прохождение этого непосредственно передает это как lvalue всегда. forward
магия, необходимая, чтобы передать это как правильную ценность,
Код, который всегда проходит через lvalue, скорее всего, будет страдать с точки зрения производительности, но я бы сказал, что вы можете игнорировать это, думая об этой конкретной проблеме. Существует более насущная проблема не всегда передавать lvalue: в то время как копирование некоторых типов может быть дорогим, некоторые другие типы не могут быть скопированы совсем, лайк std::unique_ptr
, Для этих типов сохранение rvaleness при пересылке зависит не от производительности, а от того, чтобы ваш код даже компилировался.
Вы не должны пересылать переменную более одного раза.