据我所知,在 C++11 中,通用引用应始终与 一起使用std::forward
,但我不确定如果std::forward
不使用会出现什么样的问题。
template <T>
void f(T&& x);
{
// What if x is used without std::forward<T>(x) ?
}
您能否提供一些在这种情况下可能出现的问题的说明?
据我所知,在 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
for range或 for action是错误的。假设是这样f
调用的:
f(someType{});
如果身体f
对x
foo(x);
并且有两个重载foo
void foo(someType const&);
void foo(someType&&);
不使用std::forward
,作为x
左值,调用以下重载
void foo(someType const&);
这可能会花费您潜在的优化。
使用
foo(std::forward<T>(x));
确保选择了正确的过载foo
。
有名字的东西是左值。这意味着在函数体中,t
是一个左值。通用引用最终是左值引用还是右值引用并不重要。如果它被命名,它是一个左值。
如果您因此直接传递该参数,您将传递一个左值。
在您只想将不透明参数传递给另一个函数的情况下,您希望完全按原样传递它。如果它是一个左值,你想把它作为一个左值传递;如果它是一个右值,你想传递一个右值。如前所述,直接传递它总是作为左值传递。forward
是否需要将其作为正确的值传递,
从性能角度来看,总是传递左值的代码可能会受到影响,但我想说,在考虑这个特定问题时,您可以忽略这一点。不总是传递左值有一个更紧迫的问题:虽然复制某些类型可能很昂贵,但某些其他类型根本无法复制,例如std::unique_ptr
. 对于那些在转发时保留右值的类型不是性能问题,而是让您的代码甚至可以编译。
您不应多次转发变量。