未执行左值到右值的转换
Lvalue to rvalue conversion not performed
下面的函数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);
}
`-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);
}
`-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'
为什么?转换有时是可选的吗?
AST 显示解析了 A
的构造函数,即采用左值 const A&
(main
中的 a
)并构造 a
在 f(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'
Why? Is the conversion optional sometimes?
不需要,已屏蔽。
对于 class 类型 A
,f(a);
导致调用 A
的复制构造函数。隐式定义的复制构造函数采用左值引用(即 const A&
),并且在绑定左值引用时抑制左值到右值的转换。
(5.1) If the reference is an lvalue reference ...
...
[ Note: The usual lvalue-to-rvalue, array-to-pointer, and function-to-pointer standard conversions are not needed, and therefore are suppressed, when such direct bindings to lvalues are done. — end note ]
下面的函数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);
}
`-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);
}
`-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'
为什么?转换有时是可选的吗?
AST 显示解析了 A
的构造函数,即采用左值 const A&
(main
中的 a
)并构造 a
在 f(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'
Why? Is the conversion optional sometimes?
不需要,已屏蔽。
对于 class 类型 A
,f(a);
导致调用 A
的复制构造函数。隐式定义的复制构造函数采用左值引用(即 const A&
),并且在绑定左值引用时抑制左值到右值的转换。
(5.1) If the reference is an lvalue reference ...
...
[ Note: The usual lvalue-to-rvalue, array-to-pointer, and function-to-pointer standard conversions are not needed, and therefore are suppressed, when such direct bindings to lvalues are done. — end note ]