【问题标题】: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)。

标签: c++ function reference constants


【解决方案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 检查图片以获得更好的理解。
    猜你喜欢
    • 1970-01-01
    • 2011-01-03
    • 1970-01-01
    • 1970-01-01
    • 2010-11-22
    • 2019-09-06
    • 2012-03-21
    • 2020-07-11
    • 1970-01-01
    相关资源
    最近更新 更多