gpt4 book ai didi

c++ - 即将超出范围的变量是左值还是 x 值?

转载 作者:行者123 更新时间:2023-12-04 11:58:21 25 4
gpt4 key购买 nike

当一个即将超出范围的变量被返回或抛出时,它的资源可以被重用,即它可以被移出,如下面的 C++ 程序所示:

struct X {
X() {
std::cout << "X()\n";
}

X(X&&) {
std::cout << "X(X&&)\n";
}

~X() {
std::cout << "~X()\n";
}
};

X f() {
X x;
std::cout << "return\n";
return x;
}

int main() {
try {
X x = f();
std::cout << "throw\n";
throw x;
} catch (...) {
std::cout << "catch\n";
}
return 0;
}
编译(我们使用标志 -fno-elide-constructors 关闭复制/move 省略)、链接和执行:
clang++ -std=c++17 -O2 -Wall -pedantic -pthread -fno-elide-constructors\
main.cpp && ./a.out
输出:

X()
return
X(X&&)
~X()
throw
X(X&&)
~X()
catch
~X()

x在上述声明中 return x;throw x;表示其资源可以重用的对象。
在工作草案中,C++ 编程语言标准, [basic.lval-1] ,我们对值类别有以下定义:
  • A glvalue is an expression whose evaluation determines the identity of an object or function.
  • An xvalue is a glvalue that denotes an object whose resources can be reused (usually because it is near the end of its lifetime).
  • An lvalue is a glvalue that is not an xvalue.

x也是如此左值还是 xvalue?

最佳答案

xlvalue本身。

The following expressions are lvalue expressions:

  • the name of a variable, a function, a template parameter object (since C++20), or a data member, regardless of type, such as std::cin or std::endl. Even if the variable's type is rvalue reference, the expression consisting of its name is an lvalue expression;

对于局部变量为 x , 在 return statementthrow expression , 初始化的重载解析分两个阶段进行;首先好像 x是一个右值表达式(然后可能会选择 move 构造函数)。
return statement :

(Since C++11) then overload resolution to select the constructor to use for initialization of the returned value or, for co_return, to select the overload of promise.return_value() (since C++20) is performed twice:

  • first as if expression were an rvalue expression (thus it may select the move constructor), and

throw expression :
  • This may also call the move constructor for lvalue expressions if they name local variables or function or catch-clause parameters whose scope does not extend past the innermost enclosing try-block (if any), by same two-step overload resolution as in return statement (since C++17)

作为效果,在这两种情况下都选择了 move 构造函数。这是专为 return 设计的和 throw , 不代表 xrvaluexvalue完全。如果你这样写 X x2(x);f() ,复制构造函数将被选择(并导致错误,因为复制构造函数被隐式删除)。
从标准, [class.copy.elision]/3 :

An implicitly movable entity is a variable of automatic storage duration that is either a non-volatile object or an rvalue reference to a non-volatile object type. In the following copy-initialization contexts, a move operation is first considered before attempting a copy operation:

(3.1) -If the expression in a return ([stmt.return]) or co_­return ([stmt.return.coroutine]) statement is a (possibly parenthesized) id-expression that names an implicitly movable entity declared in the body or parameter-declaration-clause of the innermost enclosing function or lambda-expression, or

(3.2) -if the operand of a throw-expression ([expr.throw]) is a (possibly parenthesized) id-expression that names an implicitly movable entity that belongs to a scope that does not contain the compound-statement of the innermost try-block or function-try-block (if any) whose compound-statement or ctor-initializer contains the throw-expression,

overload resolution to select the constructor for the copy or the return_­value overload to call is first performed as if the expression or operand were an rvalue. If the first overload resolution fails or was not performed, overload resolution is performed again, considering the expression or operand as an lvalue.


[expr.prim.id.unqual]/3 :

The expression is an lvalue if the entity is a function, variable, structured binding, data member, or template parameter object and a prvalue otherwise ([basic.lval]);


[basic.lval] :

(1.1) -A glvalue is an expression whose evaluation determines the identity of an object or function.

(1.2) -A prvalue is an expression whose evaluation initializes an object or computes the value of an operand of an operator, as specified by the context in which it appears, or an expression that has type cv void.

(1.3) -An xvalue is a glvalue that denotes an object whose resources can be reused (usually because it is near the end of its lifetime).

(1.4) -An lvalue is a glvalue that is not an xvalue.

(1.5) -An rvalue is a prvalue or an xvalue.

[Note 3: An expression is an xvalue if it is:

(4.1) -the result of calling a function, whether implicitly or explicitly, whose return type is an rvalue reference to object type ([expr.call]),

(4.2) -a cast to an rvalue reference to object type ([expr.type.conv], [expr.dynamic.cast], [expr.static.cast] [expr.reinterpret.cast], [expr.const.cast], [expr.cast]),

(4.3) -a subscripting operation with an xvalue array operand ([expr.sub]),

(4.4) -a class member access expression designating a non-static data member of non-reference type in which the object expression is an xvalue ([expr.ref]), or

(4.5) -a .* pointer-to-member expression in which the first operand is an xvalue and the second operand is a pointer to data member ([expr.mptr.oper]).

关于c++ - 即将超出范围的变量是左值还是 x 值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69099481/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com