krz*_*ofk 6 c++ language-lawyer c++11 c++17 value-categories
我以为我已经设法完全理解(在其他SO问题的帮助下,谢谢)关于值类别的C ++ 17的更改,但是现在我注意到了这个问题,这表明我不太了解它们。
在C ++ 11中,对值类别有“具有身份/可以从中移出”的解释,并且cppreference中仍然存在“身份”的含义的定义:
具有同一性:可以通过比较对象的地址或它们标识的功能(直接或间接获得)来确定该表达式是否与另一个表达式引用相同的实体。
在C ++ 17中,“具有身份/可以从其移出”不再成立,但是新定义也基于“身份”的概念:
glvalue(“广义” lvalue)是一个表达式,其求值确定对象,位字段或函数的身份;
我的问题/误解是:这是“身份”的相同意思,还是不同的“身份”?据我了解,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
Run Code Online (Sandbox Code Playgroud)
在第二和第三种情况下,我获得一个xvalue,这意味着它应该具有一个标识。因此,我应该能够得到它的地址 [编辑:]我应该能够确定它是否与某些其他表达式引用相同的实体,但是我认为我不能。当然,在第三种情况下,我可以将“&r”作为单独的命令执行,然后将其地址与另一个表达式的地址进行比较,但这是因为A &&是左值。是通过A &&取得地址,在这种情况下,“直接或间接获得”是什么意思?我认为这不是正确的答案,因为在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;
Run Code Online (Sandbox Code Playgroud)
然而,尽管r所引用的对象的生命周期延长了,但它仍然是一个临时对象,在c ++ 11中,临时对象是prvalues。因此,我假设我可以将A &&绑定到该事实(与任何左值一样,我可以接受一个地址,但只能在一个单独的表达式中)不足以得出其评估确定身份的结论(毕竟,无论发生什么情况, “&r;”行不是我的原始表达式求值的一部分),但是在c ++ 17中,它看起来像是唯一可能的解释?
您能通过确定我写的哪一部分不正确来帮助我吗?还是正确,答案仅仅是“身份”一词改变了其含义?
为什么您认为 C++11 概念不再适用?该页面说该版本引入了 \xe2\x80\x9chas 身份 \xe2\x80\x9d 想法,而不是 \xe2\x80\x99s 是唯一使用它的版本。C++17 所做的是说,纯右值 \xe2\x80\x9c 等到 \xe2\x80\x9d 为止,它们用于初始化对象以完全成为对象。(因此,它将 \xe2\x80\x9c 作为一个对象 \xe2\x80\x9d 与 \xe2\x80\x9chahaving 身份 \xe2\x80\x9d 合并,这更简单;显然每个对象都可以有this检测到。)
这真正的意思是,目标对象的地址被无形地传递到纯右值构造的位置,以便它从一开始就出现在正确的位置。编译器已经在 RVO 名称下这样做了,但这次更改保证了这一点并消除了正式的可移动性限制。
\n\nxvalue 当然有一个身份:如果您通过(任一类型)引用将纯右值传递给函数,它就可以获取其地址。它甚至可以返回它,以便(在同一个完整表达式期间)创建它的函数可以使用它的地址。禁止获取临时地址是一项单独的安全措施,即使在(例如)使用static_cast<A&&>(get_a())强制临时实现之后也适用。(但是,它不能\xe2\x80\x99 阻止您获取引用从另一个函数返回的临时值的泛左值的地址。)
| 归档时间: |
|
| 查看次数: |
151 次 |
| 最近记录: |