cppreference 是否使用术语“[对象的] 身份”对于 c++11 和 c++17 有两种不同的含义?
Is cppreference using the term "[Object's] identity" is two different meanings for c++11 and for c++17?
我以为我已经设法完全理解(在其他 SO 问题的帮助下,谢谢)C++17 关于值类别的变化,但现在我注意到了这个问题,这表明我真的不理解他们。
在 C++11 中,有一个 "has identity / can be moved from" 值类别的解释,并且 "identity" 含义的定义仍然存在于 cppreference:
has identity: it's possible to determine whether the expression refers to the same entity as another expression, such as by comparing addresses of the objects or the functions they identify (obtained directly or indirectly).
在C++17中,"has identity / can be moved from"不再成立,但新的定义也是基于"identity"的概念:
a glvalue (“generalized” lvalue) is an expression whose evaluation determines the identity of an object, bit-field, or function;
我的question/misunderstanding是:这个和"identity"是同一个意思,还是不一样"identity"?按照我的理解,c++17中的情况是这样的:
A f() { return A(); }
A a = f(); // 1: f() is a prvalue expression, used to directly initialize a.
f(); // 2: f() is a prvalue expr., converted to xvalue by temporary materialization
A&& r = f(); // 3: f() is a prvalue expr., converted to xvalue by temporary materialization
在第二种和第三种情况下,我获得了一个xvalue,这意味着它应该有一个标识。所以我应该能够 获取它的地址 [已编辑:] 我应该能够确定它是否指代与其他表达式相同的实体,但我认为我不能。当然,在第三种情况下,我可以将“&r”作为一个单独的命令执行,然后将其地址与另一个表达式的地址进行比较,但那是因为 A&& 是一个左值。在这种情况下,通过 A&& 获取地址是什么意思 "obtained directly or indirectly"?我认为这不是正确答案,因为在 C++11 中我也可以轻松做到
A&& r = f(); // 4: f() is a prvalue expression. Temporary materialization does
// not happen, the temporary (prvalue) gets its lifetime
// extended to match the lifetime of the reference
&r;
尽管 r 引用的对象的生命周期延长了,但它仍然是一个临时对象,而在 c++11 中,临时对象是纯右值。所以我假设我可以将 A&& 绑定到它(其中,像任何左值一样,我可以获取一个地址,但只能在一个单独的表达式中)这一事实不足以得出结论,它的评估决定了一个身份(毕竟,无论发生什么"&r;" 行不是我原始表达式求值的一部分),但在 C++17 中,在我看来这将是唯一可能的解释?
你能帮我看看我写的哪一部分不对吗?或者它是正确的,答案只是"identity"这个词已经改变了它的意思?
为什么您认为 C++11 概念不再适用?该页面说该版本引入了“有身份”的想法,而不是它是唯一使用它的版本。 C++17 所做的是说纯右值“等到”它们被用于初始化一个对象以完全成为一个对象。 (因此它把“是一个对象”和“有身份”合并起来,这样更简单;说白了每个对象都可以this
被检测到。)
真正的意思是目标对象的地址被无形地传递到纯右值构造的位置,以便它从一开始就出现在正确的位置。编译器已经在 RVO 名称下执行此操作,但更改保证并删除了正式的可移动性限制。
xvalue 当然有一个身份:如果你通过(任何一种)引用将 prvalue 传递给函数,它可以获取它的地址。它甚至可以 return 它以便(在同一个完整表达式中)创建它的函数可以使用它的地址。禁止获取临时地址是一项单独的安全措施,即使在(比如)使用 static_cast<A&&>(get_a())
强制临时物化之后也适用。 (但是,它不能阻止您从另一个函数中获取引用临时 returned 的泛左值的地址。)
我以为我已经设法完全理解(在其他 SO 问题的帮助下,谢谢)C++17 关于值类别的变化,但现在我注意到了这个问题,这表明我真的不理解他们。
在 C++11 中,有一个 "has identity / can be moved from" 值类别的解释,并且 "identity" 含义的定义仍然存在于 cppreference:
has identity: it's possible to determine whether the expression refers to the same entity as another expression, such as by comparing addresses of the objects or the functions they identify (obtained directly or indirectly).
在C++17中,"has identity / can be moved from"不再成立,但新的定义也是基于"identity"的概念:
a glvalue (“generalized” lvalue) is an expression whose evaluation determines the identity of an object, bit-field, or function;
我的question/misunderstanding是:这个和"identity"是同一个意思,还是不一样"identity"?按照我的理解,c++17中的情况是这样的:
A f() { return A(); }
A a = f(); // 1: f() is a prvalue expression, used to directly initialize a.
f(); // 2: f() is a prvalue expr., converted to xvalue by temporary materialization
A&& r = f(); // 3: f() is a prvalue expr., converted to xvalue by temporary materialization
在第二种和第三种情况下,我获得了一个xvalue,这意味着它应该有一个标识。所以我应该能够 获取它的地址 [已编辑:] 我应该能够确定它是否指代与其他表达式相同的实体,但我认为我不能。当然,在第三种情况下,我可以将“&r”作为一个单独的命令执行,然后将其地址与另一个表达式的地址进行比较,但那是因为 A&& 是一个左值。在这种情况下,通过 A&& 获取地址是什么意思 "obtained directly or indirectly"?我认为这不是正确答案,因为在 C++11 中我也可以轻松做到
A&& r = f(); // 4: f() is a prvalue expression. Temporary materialization does
// not happen, the temporary (prvalue) gets its lifetime
// extended to match the lifetime of the reference
&r;
尽管 r 引用的对象的生命周期延长了,但它仍然是一个临时对象,而在 c++11 中,临时对象是纯右值。所以我假设我可以将 A&& 绑定到它(其中,像任何左值一样,我可以获取一个地址,但只能在一个单独的表达式中)这一事实不足以得出结论,它的评估决定了一个身份(毕竟,无论发生什么"&r;" 行不是我原始表达式求值的一部分),但在 C++17 中,在我看来这将是唯一可能的解释?
你能帮我看看我写的哪一部分不对吗?或者它是正确的,答案只是"identity"这个词已经改变了它的意思?
为什么您认为 C++11 概念不再适用?该页面说该版本引入了“有身份”的想法,而不是它是唯一使用它的版本。 C++17 所做的是说纯右值“等到”它们被用于初始化一个对象以完全成为一个对象。 (因此它把“是一个对象”和“有身份”合并起来,这样更简单;说白了每个对象都可以this
被检测到。)
真正的意思是目标对象的地址被无形地传递到纯右值构造的位置,以便它从一开始就出现在正确的位置。编译器已经在 RVO 名称下执行此操作,但更改保证并删除了正式的可移动性限制。
xvalue 当然有一个身份:如果你通过(任何一种)引用将 prvalue 传递给函数,它可以获取它的地址。它甚至可以 return 它以便(在同一个完整表达式中)创建它的函数可以使用它的地址。禁止获取临时地址是一项单独的安全措施,即使在(比如)使用 static_cast<A&&>(get_a())
强制临时物化之后也适用。 (但是,它不能阻止您从另一个函数中获取引用临时 returned 的泛左值的地址。)