const int& 是否传递了引用或副本

did const int& pass a reference or a copy

例如,

void func(const int& a);
int main()
{
    int b=1;
    func(b*2);
}

如果const int&会传递引用,那么b*2怎么能成为引用呢?

所以这意味着它只将 b*2 的副本传递给 func()

但如果是这样,func(b)真的传递了b的引用吗?

我说得对吗?

这个例子中的&确实表示引用,所以它必须引用一个实际的对象。

b*2 在内存中创建一个 temporary int 对象(右值)。当语句 func(b*2); 完成时(即到达 ; 时),该临时文件将被销毁。

虽然语句 func(b*2) 仍然是 运行,但临时文件仍然存在。对 const 的引用可以绑定到 temporary/rvalue 对象,这就是代码编译和运行良好的原因。

但是,非常量引用不能绑定到 temporary/rvalue,只能绑定到命名变量(左值)。因此,如果您要删除 const(即 void func(int& a)),则语句 func(b*2) 将不再编译。

很简单:

int b = 1;

这里,b是一个左值。因此,当您编写 func( b ) 时,您会将 左值 传递给 func。它之所以有效,是因为 func 可以通过引用获取 lvalue

但是:

func( b*2 );

这里,b*2是一个prvalue(属于rvalue类别),当你写func( b*2 ); 然后你将 rvalue 传递给 func。它之所以有效,是因为 void func(const int& a); 有一个 const 左值引用 参数并且 const 左值引用 可以绑定到右值。

现在,如果您像这样 void func(const int&& a); 重写您的函数,使其只接受 rvalues 作为参数(注意 &&),那么 func( b*2 ) 仍会编译,但 func( b ) 不会,因为 b 是一个 lvalue 并且 lvalues 无法移动除非你像这样将它转换为 xvalue(也在 rvalueglvalue 类别下) :

func( std::move( b ) )

简而言之,std::movelvalue 转换为 xvalue 以告诉编译器它是临时的,因此可以搬离。

为了完整起见:

In C++11, expressions that:

  • have identity and cannot be moved from are called lvalue expressions;
  • have identity and can be moved from are called xvalue expressions;
  • do not have identity and can be moved from are called prvalue ("pure rvalue") expressions;
  • do not have identity and cannot be moved from are not used.

The expressions that have identity are called "glvalue expressions" (glvalue stands for "generalized lvalue"). Both lvalues and xvalues are glvalue expressions.

The expressions that can be moved from are called "rvalue expressions". Both prvalues and xvalues are rvalue expressions.

查看 value category 了解更多信息。