关于解引用运算符是否在表达式中产生对象对值的定义不明确

Definition ambiguity about whether dereference operator yields object vs value in an expression

本文关键字:对象 不明确 定义 引用 于解 运算符 是否 表达式      更新时间:2023-10-16

最近,我开始学习C++,并从这个StackOverflow资源中学习第一本书。我的问题很直接。*(在表达式中)在我所指的三个当前资源中被定义为学习C++的方式如下。

在此上下文中,*是解引用运算符。

  1. C++Primer说*产生一个对象
  2. 维基百科表示,*返回的l值与指针地址处的值相等
  3. C++教程说*返回对象的内容

其中,23对我来说完全有意义,但对1没有意义。有人能帮我把它静音吗?

在我的理解中,对象只是一个具有一定价值的内存位置。然而,对象是否可以作为关键字抛出,以反映上下文中的值,从而像1中那样取消引用指针?

我们非常感谢这些例子。

编辑:已解决,用户eerorikabolov的答案完美优雅。然而eerorika首先回答了,所以我会接受它作为答案,但所有的答案都很好。感谢SO社区。

在C++术语中,"对象"是一个占据存储区域的值。以下是对象示例:

int x = 42; // x is an object of type int
int y; // y is an object of type int
char *p = new char; // p points to an object of type char
size_t s = std::string().size(); // s is an object of type size_t; there is also an unnamed temporary object of type std::string involved in the expression

取消对指针的引用会产生一个左值,该左值指的是该点所指向的对象。让我们举另一个例子:

int i = 42;
int *p = &i;
*p = 314;

表达式CCD_ 13是引用对象CCD_。在上述代码之后,i将具有值314。

所以我想说,语句1(C++初级读本)和2(维基百科)都是正确的,用不同的词说同样的话。虽然3可能也是正确的,但我认为它有点误导,因为你通常不会说一个对象有"内容"。你可以说一个物体有一个值,或者它是一个值。


关于最初出现在问题中的声明:

在我的理解中,对象只是一个内存位置,它包含一些有用或无效的值。

第一部分实际上是正确的,对象是一个保存某些值的内存位置。然而,第二部分似乎有些混乱:在C++中,通常只在指针的上下文中谈论null。指针是一种对象类型,它包含另一个对象(或函数)的地址,或者一个特殊值,null指针值,,意思是"不指向任何东西"。大多数对象(ints、doubles、chars、数组、类类型的实例)不能说是"null"。

他们都错了。但没关系,因为它们都是正确的:)

这里唯一真正的权威是标准。标准非常精确:

§5.3.1一元运算符[expr.Unary.op]

1一元*运算符执行间接寻址:它应该是指向对象类型的指针,或者指向函数类型,结果是引用对象的左值或表达式所指向的函数。如果表达式的类型是"指向T的指针",结果的类型是"T"。

[n4296]

好了,唯一有效的定义是:

结果是指对象或函数的左值表达点

其他任何事情都是完全错误的。

除了。。。该标准对于编译器实现者和安定下来关于代码符合该标准的争论是有用的。在教学或只是谈论C++时,我们通常没有标准那么严格。我们做一些简化是为了。。。嗯,简单(有时只是出于无知)。因此,当正确的标准术语是"引用对象的左值表达式"时,我们有时会说"对象",等等

我想说,所有的定义都是正确的,它们只是使用了不同的术语或走了不同的捷径,以便于理解。

在口语中,尤其是在这种上下文中,value和object经常被用作同义词。

这三种描述都是正确的。维基百科一是这三个中最精确的描述。

维基百科对价值观的评价:

左值指的是一个对象,它持续存在于单个表达式之外。右值是一个临时值,在使用它的表达式之外不会持久存在。

C++标准(草案)对对象的描述:

C++程序中的构造创建、销毁、引用、访问和操作对象。对象是当隐式更改并集(12.3),或创建临时对象时(7.4、15.2)施工期(15.7)、使用寿命(6.8)和破坏期(15.7)……

关于内存位置:

内存位置要么是标量类型的对象,要么是相邻位字段的最大序列,所有位字段都具有非零宽度。。。


在我的理解中,对象只是一个内存位置,它包含一些有用的值或空

通常情况下,对象不能为null,除非该对象是指针或其他具有由null一词描述的特殊值的特定类型。

从文档

解引用或间接表达式的形式为

* pointer-expression
如果pointer-expression是指向函数的指针,则解引用运算符的结果是该函数的函数指示符
如果pointer-expression是指向对象的指针,则结果是指定指向对象的左值表达式。

因此以为例

int x = 5;    // x is an lvalue
int* p = &x;  // p is a pointer that points to x
*p = 7;       // dereferencing p returns the lvalue x, which you can then operate on