0

我目前正在阅读有关完美转发的文章,它指出完美转发的目的是将左值作为左值传递,将右值作为右值传递。所以我用下面的例子来理解完美转发。这里的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 调用下一个移动构造函数

4

1 回答 1

2
//Start here
foo f; // default-initialize `f`, call the default constructor
relay(std::move(f));
  • std::move(f)与 做同样的static_cast<foo&&>(f)事情,所以它实际上并没有“做”任何事情;它仅产生一个右值表达式(“f被视为右值”)。

  • 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(..)finally 调用mfoo,它按值获取参数。这会导致复制或移动,具体取决于参数表达式的类型和值类别。

由于我们这里的参数表达式是一个右值,因此将调用移动构造函数(如果存在且可访问)。

于 2014-05-11T19:24:39.203 回答