我正在做一些实验,试图了解转发是如何工作的,并且我遇到了我不理解的情况。
当我用clang 3.8 -O3
编译时class Foo {
Foo(const std::string& s) : str(s) {}
std::string str;
};
和
class Foo {
Foo(std::string&& s) : str(std::forward<std::string&>(s)) {}
std::string str;
};
在第一种情况下用Foo foo("this is a test")
构造Foo几乎快2倍。
为什么?
答案 0 :(得分:7)
只有在处理forwarding references时才需要使用std::forward
完美转发。转发引用仅存在于模板推导的上下文中。
void f(std::string&& x)
:x
是一个常规的左值引用,因为没有发生模板类型扣除。
template<typename T> void f(T&& x)
:x
是转发参考,因为T
模板扣除。
通常,除非您正在处理转发引用,否则您不想使用std::forward
。
调用std::forward
时,您必须传递转发值的确切类型。这可以这样做:std::forward<decltype(x)>(x)
。
或者,如果您有推导类型的名称:
template<typename T>
void f(T&& x)
{
something(std::forward<T>(x));
}
我会写这样的代码:
class Foo {
template<typename T>
Foo(T&& s)
: str(std::forward<decltype(s)>(s)) {}
std::string str;
};
答案 1 :(得分:2)
我认为这应该是一个移动构造函数,因此应该使用std::move
:
class Foo {
Foo(std::string&& s) : str(std::move(s)) {}
std::string str;
};
std::forward
只对斯科特迈尔斯所称的&#34;通用引用&#34;,这是rvalue引用的一个子集才有意义 - 维托里奥在他的回答中谈到了这一点。