D中的“ ==”和“是”运算符究竟比较什么?

min*_*als 1 d

从《用D编程》一书中,我了解到==操作员需要访问对象才能在返回布尔值之前评估左右表达式。因此,不适合比较对象是否为null

... ==运算符可能需要查询对象成员的值,并且尝试通过可能为null的变量访问成员将导致内存访问错误。

值相等:整本书中许多示例中出现的==运算符将变量的值进行比较。当从这个意义上说两个变量相等时,它们的值相等。

因此,让我们尝试以下方法:

import std.experimental.all;

int[] arr = [1, 1, 2, 2, 3];
arr == arr.reverse.array; // --> true
Run Code Online (Sandbox Code Playgroud)

好吧,这是意外的。例如,在Scala中,相同的表达式返回False

选中这两个内存地址后,它变得更清晰arr,并arr.reverse.array不会改变- 。因此,==尽管人们希望它可以比较数组的值而不是它们的地址,但是现在的结果是有意义的,对吗?

现在,让我们尝试使用is运算符,该运算符用于比较对象引用,并且应用于检查对象是否为null。它还用于比较类变量。

arr is arr.reverse.array; // --> false
Run Code Online (Sandbox Code Playgroud)

我希望它也会返回true,因为它会比较引用。这到底是怎么回事?为什么要is返回false==返回true

Ada*_*ppe 5

==是否比较值。is是否比较参考。您最大的错误是使用函数reverse

http://dpldocs.info/experimental-docs/std.algorithm.mutation.reverse.html

在原位反转r

强调我的。这意味着它将修改原始内容。

我怀疑您也在检查内存地址错误。如果使用&arr,则在比较局部变量的地址,而不是数组内容。这不会改变,因为它是相同的局部变量,您只是绑定到其他数组。检查.ptr而不是,&您将看到它发生了变化- .array函数始终为其分配一个新的数组。

所以==通过了,因为反向同时改变了左侧!这不是因为[1,2,3] == [3,2,1],而是因为在调用反向后,[1,2,3]本身被修改为[3,2,1] == [3,2,1]!。

现在,关于这些运算符的实际作用:==检查某种抽象的相等性。这因类型而异:可以被成员函数覆盖(这就是为什么在null类上调用它有问题的原因),并且经常进行逐成员比较(例如,数组元素或结构块)。

is另一方面,做起来要简单得多:直接比较变量,更接近抽象的身份概念,但不完全相同(就像int a = 3; int b = 3; assert(a is b);通过,因为两者均为3,但身份相同吗?)值类型。)

is 永远不会调用用户定义的函数,也永远不会成为成员引用,它只会比较位值。

(有趣的是,它float.nan is float.nan也返回true,而==不会,仅是因为它比较位值。但是并非所有的nans都具有相同的位值,因此它不能替代math模块中的isNaN!)