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::movelvalue 强制转换为 xvalue 以告诉编译器它是临时的,因此可以从中移动。

为了完整起见:

在 C++11 中,表达式:

具有标识且不能从中移动的称为左值表达式; 具有标识并且可以从中移动的称为 xvalue 表达式; 没有身份并且可以从中移动的称为prvalue(“纯右值”)表达式; 没有身份,不能从不使用。

具有同一性的表达式称为“glvalue 表达式”(glvalue 代表“广义左值”)。 lvalues 和 xvalues 都是 glvalue 表达式。

可以从中移动的表达式称为“右值表达式”。 prvalues 和 xvalues 都是右值表达式。

查看value category了解更多信息。

【讨论】:

@Altman Jeffry 检查图片以获得更好的理解。

以上是关于const int& 是不是传递了引用或副本的主要内容,如果未能解决你的问题,请参考以下文章

将const引用/指针传递给类进行存储的首选方法,而不是复制引用的对象

在 C++ 中,通过引用传递 const long double 是不是很好?

C++ 使用const 引用传递参数

const与指针

const 方法使用引用修改对象

const用法