[从《用D编程》中,我了解到==
运算符需要访问对象,以便在返回布尔值之前评估左右表达式。因此,不适合比较对象是否为null
。
... ==运算符可能需要查询对象成员的值,并且尝试通过可能为null的变量访问成员将导致内存访问错误。
also
值相等:==运算符出现在整个示例中这本书通过变量的值比较变量。当说两个变量从这个意义上说相等,它们的价值是相等的
所以,让我们尝试以下方法:
import std.experimental.all;
int[] arr = [1, 1, 2, 2, 3];
arr == arr.reverse.array; // --> true
嗯,这是意外的。例如,在Scala中,相同的表达式返回False
。
检查完arr
和arr.reverse.array
的存储地址后,它变得更加清晰-不会改变。因此,尽管==
的结果是合理的,尽管人们希望它比较数组的值而不是它们的地址,对吧?
[现在,让我们尝试is
运算符,该运算符用于比较对象引用,并且应用于检查对象是否为null
。它也用于比较类变量。
arr is arr.reverse.array; // --> false
我希望它也返回true
,因为它比较了引用。这到底是怎么回事?为什么is
相反返回false
而==
返回true
?
==
执行比较值。 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,但是它是同一身份吗?值类型的模糊cuz。)
[is
永远不会调用用户定义的函数,也永远不会成为成员引用,它只会比较位值。
((有趣的是,float.nan is float.nan
也会返回true,而==不会,仅是因为它会比较位值。但并非所有nan都具有相同的位值,因此它不能替代mathNaN在数学模块中!)