“==”和 "is" 运算符在 D 中究竟比较什么?

What exactly do the "==" and "is" operators compare in D?

从 "Programming in D" 书中我了解到 == 运算符需要访问对象,以便在 returning 布尔值之前评估左侧和右侧的表达式。因此不适合比较对象是否为null.

... the == operator may need to consult the values of the members of the objects and that attempting to access the members through a potentially null variable would cause a memory access error.

还有

Value equality: The == operator that appears in many examples throughout the book compares variables by their values. When two variables are said to be equal in that sense, their values are equal.

所以,让我们尝试以下操作:

import std.experimental.all;

int[] arr = [1, 1, 2, 2, 3];
arr == arr.reverse.array; // --> true

嗯,这是出乎意料的。例如在 Scala 中相同的表达式 returns False

检查arrarr.reverse.array的内存地址后就更清楚了——它没有改变。所以,现在 == 的结果有点道理,尽管人们希望它比较数组的值而不是它们的地址,对吧?

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

arr is arr.reverse.array; // --> false

我希望它也能 return true 因为它比较参考文献。这里到底发生了什么?为什么 is returns false== returns true

== 比较值。 is 比较引用。你的大错误是使用函数 reverse.

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

Reverses r in-place.

强调我的。也就是说修改了原来的内容。

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

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

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

另一方面,

is 做的事情要简单得多:它是直接对变量进行位比较,这更接近恒等式的抽象概念,但不完全是(如 int a = 3; int b = 3; assert(a is b); 通过,因为两者都是 3 但它是相同的标识吗?值类型的模糊 cuz。)

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

(有趣的是,float.nan is float.nan 也 returns 正确,而 == 不会,同样只是因为它比较位值。但并非所有 nans 都具有相同的位值,因此它不是替换数学模块中的 isNaN!)