2015-09-27 79 views
6

据我所知,std::forward<T>(x)相当于static_cast<T&&>(x)C++ std :: forward <T> vs static_cast <T>

但是从我所看到的,static_cast<T>(x)似乎做同样的事情,因为可以在下面的code

我的问题可以看出因此也是为什么std::forward<T>作为static_cast<T&&>(x)实现的,而不是static_cast<T>(x),如果两者都具有相同的影响?

+1

您没有尝试'int&'。 – Quentin

+0

@Quentin在这种情况下,它总是返回一个左值。 – Mikrosaft

+0

'static_cast '会创建一个右值的副本 –

回答

10

因为完美转发允许通过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创建临时对象。

+0

我刚检查过它,它实际上调用了rvalue的拷贝构造函数。 但是为什么?我读到,如果我们用rvalue调用func(),则T被推断为int &&,因此static_cast (x)将变为static_cast (x)。 那么为什么它会创建一个副本? – Mikrosaft

+2

'static_cast '可以返回一个参考:上面的答案意味着它不能。你能否澄清这个问题只发生在一个“案例”中? – Yakk

+0

@Mikrosaft:不,“T”不能推导为“int &&”,它只能是“int”或“int&'。 – myaut

2

如果T&&是一个rvalue引用,那么T是一个值,则static_cast<T>使得拷贝不是右值参考。

该副本将绑定到右值引用(就像引用),但复制/移动ctors可能被不必要地调用,并且它不是elision的候选人。

static_cast<T&&>将同时只投到一个右值引用。

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

0

我同意雅克,但它比这更糟糕。

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>更好地捕捉了意图。

相关问题