C++ std::forward<T> 对比 static_cast<T>

C++ std::forward<T> vs static_cast<T>

据我了解,std::forward<T>(x) 等同于 static_cast<T&&>(x)

但是据我所见,static_cast<T>(x)似乎做了同样的事情,如下所示code

因此我的问题是为什么 std::forward<T> 实现为 static_cast<T&&>(x),而不是 static_cast<T>(x),如果两者具有相同的效果?

因为完美转发允许同时传递 r 值引用 l 值引用 。这是通过 reference collapsing:

完成的
T = int    --> T&& = int&&
T = int&   --> T&& = int& && = int&
T = int&&  --> T&& = int&& && = int&&

在您使用 static_cast<T> 的示例中,您只是丢失了 r 值引用。它适用于基本类型(因为传递 int 通常是复制一个 CPU 寄存器值),但对于复杂类型来说很糟糕,因为它会导致通过复制 ctors 创建临时对象。

如果 T&& 是一个右值引用,那么 T 是一个值,那么 static_cast<T> 使 copy 不是右值引用。

该副本将绑定到右值引用(就像引用一样),但是 copy/move 构造函数可能会被不必要地调用,它不是省略的候选对象。

static_cast<T&&> 将同时转换为右值引用。

它们在其他方面是相同的。

我同意 Yakk 的观点,但它比那更糟。

void foo(const std::vector<int> &vec);

template<typename T>
void callFoo(T &&data)
{
    foo(static_cast<T>(data));
}

int main()
{
    callFoo(std::vector<int>{/*...*/});
}

这将始终创建一个副本。向量 移动,因为 data 作为表达式是类型 std::vector<int> 的左值,即使替换的类型是 std::vector<int>&&。请注意 Tstd::vector<int>,而不是 std::vector<int> &&。这个故事的寓意:使用标准库,它做了正确的事情,而且名称 forward 也比 static_cast<something>.

更能抓住意图