C ++中值类别的定义中“身份”的含义是什么

时间:2018-11-23 08:43:52

标签: c++ language-lawyer lvalue static-typing

简而言之,您可以回答有关身份的部分,谢谢。这个问题的主要重点是从2开始。关于身份,我只是想提供我目前的理解的背景信息/背景,因此它可以帮助您在编写答案时确定深度。


我想了解C ++中类型系统和值类别的概况。我在网上搜索/阅读了许多问题和资源,但是每个人的解释都不同,所以我很困惑。如果有人可以提供有关以下内容的信息,我将列出我无法掌握的部分

  1. cppreference.com, first line上:

      

    对象,引用,函数 ,包括 函数模板专业化 表达式< / em> 具有一个名为type的属性,该属性不仅限制了这些实体允许的操作,而且还为其他通用位序列提供了语义。

    我的问题:

    • 表达式具有类型是什么意思?是评估后最终结果的类型?
    • 我现在不想学习模板,这会妨碍对基本部分的学习吗(从您的专家的角度来看)?我花了一些时间才意识到转发引用和右值引用是不同的东西,前者是用于模板的。
  2. 值类别:

    我读了这个answer of - What are rvalues, lvalues, xvalues, glvalues, and prvalues?,这个词让我很困扰,是 身份 ,它也出现在cppreference.com - Value categories (Line 5, glvalue)上。

    我的问题:我可以说identity ==可以为其分配新值的所有内容吗?

    • 我看到人们使用 address / pointer 这个词,但这是has identity iff has address/pointer吗?我想要确切的用语。
    • 在阅读cppreference.com时,我遇到了位域的概念,似乎给定了位域结构a,它的位域a.m没有地址?这是使用身份标识而不是地址/指针的原因吗?
    • 我发现了a blog post explaining this,但是它的左值定义是违反直觉的:左值表示对象,其资源无法重用,为什么不呢?

3 个答案:

答案 0 :(得分:4)

identity是一个哲学概念。这是使它与众不同的特性。没有两个“事物”可以具有相同的身份。

具有身份的事物是实体。

[basic.lval]

  

glvalue 是一个表达式,其求值确定对象,位字段或函数的身份。

表达式中的名称只能指定一个对象。因此,表达式中的名称就是身份。它定义为左值(例如,参见expr.prim.id.unqual

在给定地址和给定时间,不能有2个相同类型的对象(可以将对象嵌套在彼此内部,...)。因此,取消引用指针会得到一个 lvalue

引用始终指定一个实体。因此,每个在调用时返回引用的函数都会生成一个 glvalue

...

xvalue 是一个标记,只能通过强制转换(或绑定到临时实现)生成。它是一个glvalue,表示可以重用其资源的对象或位字段 basic.lval

xvalue lvalue 之间的差异用于生成有效的代码。但是 xvalue 作为 lvalue glvalue :它们带来实体的身份。

...

prvalue 是与任何对象都不相关的表达式的结果。这是调用具有非引用返回类型的函数的结果,或者是某些内置运算符调用的结果。在c ++中,表达式不是实体,因此它没有身份。

prvalue 可能有一个结果对象,它可以是一个临时对象。临时实体是一个实体,需要时会实体化(当尝试获取对它的引用或丢弃 prvalue 时)。


表达式的类型在[expr.type]中明确定义:

  

如果表达式最初的类型为“对T的引用”([dcl.ref],[dcl.init.ref]),则在进行任何进一步分析之前,将类型调整为T。   表达式指定由引用表示的对象或功能,并且表达式取决于表达式是左值还是x值。   [注意:在引用的生存期开始之前或结束之后,行为是不确定的(请参阅[basic.life])。   —注   ]

     

如果prvalue最初具有类型“ cv T”,其中T是cv不合格的非类,非数组类型,则在进行任何进一步分析之前,将表达式的类型调整为T。

表达式不能具有引用类型。

答案 1 :(得分:2)

  1. 表达式的类型是,如果以及何时对表达式求值,其结果将具有的类型。表达式没有需要计算,但是所有表达式都有类型。类型是静态属性
  2. 没有确切的身份定义,也没有迹象表明哪些实体具有或没有身份。这是一个泥泞的概念,最好不去管它。忽略它。有人说对象身份是它的地址,但是这个概念是没有用的。那为什么不只是谈论其地址呢?那位域呢?它们是没有地址的对象,它们没有身份吗?其他人则说,左值具有身份,右值不具有身份,但这同样是多余的。

答案 2 :(得分:1)

首先,如果您真的想学习C ++的形式主义/细节,则应该参考这些标准(或它们的草案);而不是Wiki页面(可能正确或不正确;尽管cppreference通常非常好)。参见Where do I find the current C or C++ standard documents?

话虽如此,没有必要研究C ++标准来使用该语言。实际上,大多数开发人员不会,而且可以肯定的是,他们并不是要学习C ++。它们是正式文件,不是教学材料。因此,如果您只是在学习C ++,请购买一本不错的书。请参见The Definitive C++ Book Guide and List


  

表达式具有类型是什么意思?是评估后最终结果的类型吗?

否,不需要对其进行评估(即在运行时)以具有类型。例如,sizeof expr的类型为std::size_t,但是expr未被评估。

  

我现在不想学习模板,这会妨碍对基本部分的学习吗(从您的专家的角度来看)?我花了一些时间才意识到转发引用和右值引用是不同的东西,前者是用于模板的。

实际上,这是另一回事,如果您想学习C ++的实际用途,则肯定至少需要了解有关模板的基础知识(如果只是使用标准库而不会完全迷失)。

但是,您不需要正式地知道关于值类型,右值引用或模板本身如何工作的所有知识,就可以进行编程。

  

这个词让我很困扰,是身份

标准中没有“身份”的定义。在C ++ 17中,它在一些地方使用,例如在定义glvalue时:

  

- glvalue 是一个表达式,其求值确定对象,位字段或函数的身份。

但是,实际上,您可以说“具有身份”的意思是“实际上存在于内存中的某个位置(如果需要)”。您可以做的最好的操作就是阅读what Stroustrup wrote

  

“具有身份” –即地址,指针,用户可以确定两个副本是否相同,等等。

您也可以用相反的方式来思考:glvalue(具有身份的事物)是任何不是prvalue的表达式,如果有帮助的话。