const int& 是不是传递了引用或副本
Posted
技术标签:
【中文标题】const int& 是不是传递了引用或副本【英文标题】:did const int& pass a reference or a copyconst int& 是否传递了引用或副本 【发布时间】:2022-01-19 07:29:12 【问题描述】:例如,
void func(const int& a);
int main()
int b=1;
func(b*2);
如果const int&
会传递一个引用,那么b*2
怎么会是一个引用?
所以这意味着它只将b*2
的副本传递给func()
?
但如果是这样,func(b)
真的传递了b
的引用吗?
我说的对吗?
【问题讨论】:
对常量的引用可以绑定到临时值(又名rvalues)。 【参考方案1】:这个例子中的&
确实表示一个引用,所以它必须引用一个实际的对象。
b*2
在内存中创建一个 临时 int
对象(右值)。当语句func(b*2);
完成时(即到达;
时),该临时文件将被销毁。
虽然func(b*2)
语句仍在运行,但临时语句仍然存在。 const 引用可以绑定到临时/右值对象,这就是代码编译和运行良好的原因。
但是,非常量引用不能绑定到临时/右值,只能绑定到命名变量(左值)。因此,如果您要删除 const
(即 void func(int& a)
),那么声明 func(b*2)
将不再编译。
【讨论】:
【参考方案2】:很简单:
int b = 1;
这里,b
是一个左值。因此,当您编写 func( b )
时,您会将 左值 传递给 func
。它之所以有效,是因为 func
可以通过引用获取 左值。
但是:
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(它也在 rvalue 和 glvalue 类别)像这样:
func( std::move( b ) )
简而言之,std::move
将 lvalue 强制转换为 xvalue 以告诉编译器它是临时的,因此可以从中移动。
为了完整起见:
在 C++11 中,表达式:
具有标识且不能从中移动的称为左值表达式; 具有标识并且可以从中移动的称为 xvalue 表达式; 没有身份并且可以从中移动的称为prvalue(“纯右值”)表达式; 没有身份,不能从不使用。
具有同一性的表达式称为“glvalue 表达式”(glvalue 代表“广义左值”)。 lvalues 和 xvalues 都是 glvalue 表达式。
可以从中移动的表达式称为“右值表达式”。 prvalues 和 xvalues 都是右值表达式。
查看value category了解更多信息。
【讨论】:
@Altman Jeffry 检查图片以获得更好的理解。以上是关于const int& 是不是传递了引用或副本的主要内容,如果未能解决你的问题,请参考以下文章
将const引用/指针传递给类进行存储的首选方法,而不是复制引用的对象