【问题标题】:Lvalue to rvalue conversion not performed未执行左值到右值转换
【发布时间】:2018-04-25 14:19:34
【问题描述】:

以下函数returns an rvalue

int foo()
{
    int x = 42;
    return x;    // x is converted to prvalue
}

Clang 的AST also shows the conversion:

`-FunctionDecl <line:1:1, line:5:1> line:1:5 foo 'int ()'
  `-CompoundStmt <line:2:1, line:5:1>
    |-DeclStmt <line:3:5, col:15>
    | `-VarDecl <col:5, col:13> col:9 used x 'int' cinit
    |   `-IntegerLiteral <col:13> 'int' 42
    `-ReturnStmt <line:4:5, col:12>
      `-ImplicitCastExpr <col:12> 'int' <LValueToRValue>
                                         ^^^^^^^^^^^^^^
        `-DeclRefExpr <col:12> 'int' lvalue Var 0x627a6e0 'x' 'int'

下面还执行左值到右值的转换,这次是为了参数进入函数。

void f(int i) {}
int main()
{
    int x{3};
    f(x);
}

AST includes the conversion:

`-FunctionDecl <line:2:1, line:6:1> line:2:5 main 'int ()'
  `-CompoundStmt <line:3:1, line:6:1>
    |-DeclStmt <line:4:5, col:13>
    | `-VarDecl <col:5, col:12> col:9 used x 'int' listinit
    |   `-InitListExpr <col:10, col:12> 'int'
    |     `-IntegerLiteral <col:11> 'int' 3
    `-CallExpr <line:5:5, col:8> 'void'
      |-ImplicitCastExpr <col:5> 'void (*)(int)' <FunctionToPointerDecay>
      | `-DeclRefExpr <col:5> 'void (int)' lvalue Function 0x6013660 'f' 'void (int)'
      `-ImplicitCastExpr <col:7> 'int' <LValueToRValue>
                                        ^^^^^^^^^^^^^^
        `-DeclRefExpr <col:7> 'int' lvalue Var 0x60138a0 'x' 'int'

据我了解,同理,以下也应该需要左值到右值的转换。

struct A{};
void f(A a) {}
int main()
{
    A a;
    f(a);
}

但是never shows up in the AST:

`-CallExpr <line:6:5, col:8> 'void'
  |-ImplicitCastExpr <col:5> 'void (*)(A)' <FunctionToPointerDecay>
  | `-DeclRefExpr <col:5> 'void (A)' lvalue Function 0x615e830 'f' 'void (A)'
  `-CXXConstructExpr <col:7> 'A' 'void (const A &) noexcept'
    `-ImplicitCastExpr <col:7> 'const A' lvalue <NoOp>
      `-DeclRefExpr <col:7> 'A' lvalue Var 0x615ea68 'a' 'A'

为什么?转换有时是可选的吗?

【问题讨论】:

    标签: c++ clang lvalue-to-rvalue


    【解决方案1】:

    为什么?转换有时是可选的吗?

    它不需要,并且被禁止。

    对于类类型Af(a); 导致调用A 的复制构造函数。隐式定义的复制构造函数采用左值引用(即const A&amp;),并且在绑定左值引用时禁止左值到右值的转换。

    [dcl.init.ref]/5.1:

    (5.1) 如果引用是左值引用...

    ...

    [ 注意:通常的左值到右值、数组到指针和函数到指针的标准转换是不需要的,因此在完成与左值的直接绑定时会被抑制。 — 尾注 ]

    【讨论】:

      【解决方案2】:

      AST 表明A 的构造函数已被解析,即采用左值const A&amp;main 中的a)并构造f(A a) 中的a。这里没有右值。

      `-CallExpr <line:6:5, col:8> 'void'
        |-ImplicitCastExpr <col:5> 'void (*)(A)' <FunctionToPointerDecay>
        | `-DeclRefExpr <col:5> 'void (A)' lvalue Function 0x615e830 'f' 'void (A)'
        `-CXXConstructExpr <col:7> 'A' 'void (const A &) noexcept'
          ^^^^^^^^^^^^^^^^                    ^^^^^^^^^
          `-ImplicitCastExpr <col:7> 'const A' lvalue <NoOp>
            `-DeclRefExpr <col:7> 'A' lvalue Var 0x615ea68 'a' 'A'
      

      【讨论】:

        猜你喜欢
        • 2017-11-24
        • 1970-01-01
        • 2013-07-12
        • 1970-01-01
        • 2014-01-17
        • 2020-09-19
        • 1970-01-01
        • 2017-08-18
        • 1970-01-01
        相关资源
        最近更新 更多