我目前正在阅读有关完美转发的内容,并指出完美转发的目的是将左值作为左值和右值作为右值传递。所以我使用以下示例来了解完美转发。这里的foo
对象有一个复制和移动cnstr,它还有一个复制和移动赋值运算符。
void mfoo(foo arg)
{
.......
}
template<typename T>
void relay(T&& arg)
{
mfoo(std::forward<T>(arg));
}
//Start here
foo f;
relay(std::move(f));
现在我在VS2012中测试此代码,移动构造函数只调用一次。我期待它被召唤两次。如果有人能向我解释,我将不胜感激。 我期望在中继处调用第一个移动构造函数,并在mfoo
调用下一个移动构造函数答案 0 :(得分:2)
//Start here
foo f; // default-initialize `f`, call the default constructor
relay(std::move(f));
std::move(f)
与static_cast<foo&&>(f)
的效果相同,所以实际上并没有&#34;做&#34;任何事情;它只产生一个右值表达式(&#34; f
被视为右值&#34;)。
relay( std::move(f) )
实例化void relay<foo>(foo&& arg)
并调用此函数。该参数是参数,与参数兼容,因此不会调用构造函数。
mfoo(std::forward<T>(arg))
std::forward<T>(arg)
是左值引用,则 arg
会将T
作为左值,如果T
不是左值引用,则会将其作为右值。即,对于T == foo&&
,它与std::move(arg)
的作用相同。没有构造函数被调用。
mfoo(..)
最后调用mfoo
,它的参数的值为。这会导致复制或移动,具体取决于参数表达式的类型和值类别。
由于我们的参数表达式是一个右值,因此将调用移动构造函数(如果存在且可访问)。