C++11 "T&&"参数失去其"&&"正确的术语?

C++11 `T&&` parameter losing its `&&` correct terminology?

本文关键字:术语 失去 参数 C++11      更新时间:2023-10-16

以下c++ 11代码无法编译:

struct T {};
void f(T&&) { }
void g(T&& t) { f(t); }
int main()
{
    g(T());
}

正确的方法是:

void g(T&& t) { f(move(t)); }

这很难用正确的自然语言术语来解释。参数t似乎失去了它的"&&"状态,它需要与std::move一起恢复。

g(T())中的T()叫什么?

g(T&& t)中的T&&是什么?

g(T&& t)中的t是什么?

f(t)f(move(t))中的t是什么?

move(t)的返回值是什么?

你认为整体效果是什么?

标准的哪个部分处理这个问题?

关键是参数T&& b只能绑定到右值,但是当以后引用表达式b时,它是左值。

所以函数的实参必须是右值,但在函数体内部,形参是左值,因为这时你已经绑定了对它的引用并给了它一个名字,它不再是一个未命名的临时对象了。

表达式具有类型(例如int, string等),并且具有值类别(例如左值或右值),这两者是不同的。

声明为T&& b的命名变量类型为"对T的右值引用",并且只能绑定到右值,但是当您稍后使用该引用时,表达式b具有值类别"左值",因为它有名称并引用某个对象(无论引用绑定到什么对象,即使该对象是右值)。这意味着将b传递给另一个接受右值的函数,你不能只说f(b),因为b是左值,所以你必须通过std::move(b)将它(返回)转换为右值。

所有参数都是左值,即使它们的类型是"右值引用"。它们都有名字,所以你可以随时引用它们。如果命名的右值引用是右值,您将得到令人惊讶的行为。我们不希望从左值隐式移动,这就是为什么你必须显式地写std::move

g(T())中的T()叫什么?

临时的(可移动的)。

你叫什么T&&在g (T&和;

t) ?

T&和;是一个r值引用,表示一个可以移动的对象。

g(t &&

t) ?

t实际上是一个左值,因为您可以通过名称引用它。

f(t)和f(move(t))中的t叫什么?

  1. l值
  2. 当move()返回时将l值转换为r值引用

move(t)的返回值是什么?

r值引用

作为注释;你可能应该调用结构体C,并写一个单独的例子,其中T实际上是模板化的。代码需要不同,因为在函数template< typename T > void f( T&& t );中,您不能简单地使用std::move()而不小心非常,因为T实际上可以是const&,在这种情况下,您不能使用std::move(),而是使用完美转发std::forward< T >( t )

g(T())中的T()叫什么?

这是一个临时对象和r值。

你叫什么T&&在g (T&和;

t) ?

你称它为r值引用

原因

void g(T&& t) { f(t); }

不能工作是因为r值引用不能绑定到命名对象(即使该命名对象恰好是另一个r值引用)。

参数t不丢失其"状态"。简单地说,参数t是一个左值,尽管它是一个右值引用。请记住,左值和右值是正交的概念,适用于值和值引用(包括右值引用)。因此,右值引用既可以是左值,也可以是右值。如果它有一个名称,就像在您的示例中一样,它是一个左值。这使得类型系统正交,这是一个很好的特性。