考虑这个C#类:
class Node
{
public Node Next;
}
考虑这两种情况:
Node A = new Node();
Node B = A;
B=(B.Next = new Node());
和
Node A = new Node();
Node B = A;
B.Next = (B=new Node());
为什么他们会产生相同的结果!?
(A)->(B)->Null
我认为第二种情况会产生一个指向自身的节点,因为运算符优先...
Java 和 Python 的情况也是如此吗? 感谢
答案 0 :(得分:2)
在Python中,您无法按照自己的方式对作业进行分组。极端RHS值被分配给左侧的所有标识符。
>>> a = (b=42)
File "<stdin>", line 1
a = (b=42)
^
SyntaxError: invalid syntax
>>> a = b = 42
>>> print a,b
42 42
>>>
与您的问题类似
>>> class Node():
... def __init__(self):
... self.next = self
...
>>> n = Node()
>>> n = n.next = Node()
>>> n
<__main__.Node instance at 0x7f07c98eb200>
>>> n.next = n = Node()
>>> n
<__main__.Node instance at 0x7f07c98eb290>
答案 1 :(得分:2)
C#从左到右评估作业的各边。
所以在你的第二种情况下,它在评估RHS之前在最后一行的赋值中'评估'LHS(B.Next),并在A中得到对Next的引用。
无论您在RHS上做什么,都会被分配到此。所以在RHS上改变B太晚了。
如果没有这样做那么
B.Next = (B = null)
是一个空引用异常,它不是你所期望的那样吗?
答案 2 :(得分:2)
此行为不是运算符优先级的结果,而是Java,Python和C#中定义表达式求值顺序的规则的结果。具体来说,在Java,Python和C#中,表达式从左到右进行计算。例如,在C和C ++中,这是不正确的,你所写的结果将是未定义的。
你可能熟悉这个C拼图:
int i = 1;
printf("%d, %d\n", i++, ++i); // what is printed?
在C中,结果未定义。它可能是1, 3
,可能是2, 2
,甚至可能是其他内容。在Java C#和Python中,结果总是1, 3
(当然除了Python没有pre-orfix + ++运算符)。
运营商优先权是一个单独的问题。它定义了解析树,而不是评估的顺序。
假设您使用二进制中缀运算符op1
和op2
的新语言。并说你有以下代码:
e1 op1 e2 op2 e3
运算符优先级告诉您这是否意味着
((e1 op1 e2) op2 e3)
或者是否意味着
(e1 op1 (e2 op2 e3))
不告诉您评估e1
,e2
和e3
的顺序。
答案 3 :(得分:1)
为了完整起见,Java在这里的工作方式与C#相同。
Node A = new Node();
创建一个新节点(让我们将它命名为Node 1),然后让A指向它。
Node B = A;
这使B指向同一节点1.
A ----> [Node 1]---> null
↑
B −−−−−−−−−'
现在情况如此。所以,现在复杂的最后一行:
B.Next =
这会将节点1的下一个指针(B指向的)更改为...
(B=new Node());
...一个新节点(让我们称之为节点2),同时放入B变量。
A ----> [Node 1]---> [Node 2]----> null
↑
B −−−−−−−−−−−−−−−−−−−−−−−'
这里有趣的是,B.next
在作业的右侧之前进行评估,因此它与您在此处编写A.next
的内容相同。