当左值传递给T&&时,会发生什么?

时间:2014-02-07 09:34:49

标签: c++ templates c++11 stl rvalue-reference

以下是 C ++ Primer 5th Edition 的练习:

  

练习16.45:给出以下模板,解释如果发生了什么   我们称g为字面值,例如42.如果我们将g称为a   int类型的变量? P.690

template <typename T>
void g(T&& val)
{
    std::vector<T> v;
}

int main()
{
    //g(42);

    int i;
    g(i);
}

在呼叫42时,它已编译。

当在i时,编译器抱怨了很多错误,其中一部分粘贴如下。

forming pointer to reference type 'int&'

我的问题是

  1. 在这种情况下调用字面值42时,T的推断类型是什么?

  2. i时,为什么不编译?如何理解这些错误消息?

1 个答案:

答案 0 :(得分:5)

来自http://thbecker.net/articles/rvalue_references/section_08.html

其余两个rvalue引用规则中的第一个也会影响旧式左值引用。回想一下,在11 C ++之前,不允许引用引用:类似于A&amp; A; &安培;会导致编译错误。相比之下,C ++ 11引入了以下参考折叠规则:

A& & becomes A&
A& && becomes A&
A&& & becomes A&
A&& && becomes A&&

其次,函数模板有一个特殊的模板参数推导规则,它通过对模板参数的右值引用来获取参数:

template<typename T>
void foo(T&&);

以下适用:

  • 当在类型A的左值上调用foo时,则T解析为A&amp;因此,通过上面的参考折叠规则,论证类型实际上变为A&amp;。
  • 当在类型A的右值上调用foo时,则T解析为A,因此参数类型变为A&amp;&amp;。

所以情况1,当传递42时,你用r值调用g,所以T被解析为int因此g的参数是int&&而std :: vector是合法的。

在案例2中,当传递i时,您使用左值调用g,因此T被解析为int&因此g的参数为int&std::vector<int&> NOT < / strong>合法。

删除带向量的行,它在两种情况下都能正常工作。