请考虑以下代码段:
C ++:
#include <iostream>
using namespace std;
int main()
{
int x = 10, y = 20;
y = x + (x=y)*0;
cout << y;
return 0;
}
,其结果为20
,因为y
的值已分配给x
,因为根据Operator Precedence Table首先执行括号。
VB.NET:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim x As Integer = 10
Dim y As Integer = 20
y = x + (x = y) * 0
MsgBox(y)
End Sub
而是给出10
的结果。
答案 0 :(得分:5)
与C ++不同,VB.NET的=
并不总是一项任务。如果它出现在表达式中,它也可以是等式比较运算符(C ++中的==
)。因此你的两个表达方式是不一样的。它们甚至不相同。 VB.NET代码没有你想象的那样。
首先是你的C ++代码:就像你说的那样,作业(似乎不正确;请参阅Jens' answer。)由于你最终x=y
首先出现;因此,你的代码大致相当于:y
为20
,很可能是你的C ++编译器评估了您的代码,就像您编写了这样:
int x = 10, y = 20;
x = y;
y = x + x*0; // which is equivalent to `y = 20 + 20*0;`, or `y = 20 + 0;`, or `y = 20;`
然而,在VB.NET中,因为子表达式=
中的(x=y)
实际上并未被解释为赋值,但作为比较,代码等同于:
Dim x As Integer = 10
Dim y As Integer = 20
y = 10 + False*0 ' which is equivalent to `y = 10 + 0*0`, or `y = 10` '
这里,运算符优先级甚至没有发挥作用,而是将布尔值False
隐式类型转换为数字0
。
(以防万一你想知道:在VB.NET中,表达式中的赋值是不可能的。赋值必须始终是它们自己的完整语句,它们不能“内联”发生。否则就无法判断是否{表达式中的{1}}表示赋值或比较,因为两者都使用相同的运算符。)
答案 1 :(得分:4)
您的C ++代码段是未定义的行为。使用x作为第一个参数并将y赋值给x之间没有序列点,因此编译器可以按任何顺序计算子表达式。两个
在表达式中放置赋值通常也是一种非常糟糕的风格。
答案 2 :(得分:4)
这个答案仅作为评论,但其长度很快就超出了限制。对不起:)
您将运算符优先级与评估顺序混淆。 (这是一种非常普遍的现象,所以不要感觉不好)。让我试着用更简单的例子来解释更熟悉的算子:
如果你有一个像a + b * c
这样的表达式,那么乘法将始终在加法之前发生,因为*
运算符比+
<更紧密地绑定EM>运算符的。到现在为止还挺好?重要的是,允许C ++以任何顺序评估操作数 a
,b
和c
。如果其中一个操作数具有影响另一个操作数的副作用,那么这有两个原因:
顺便说一句,Java总是首先评估a
,然后评估b
,然后评估c
,“尽管”在添加之前发生了乘法。伪字节码看起来像push a; push b; push c; mul; add;
(你没有问过Java,但是我想提一下Java来举例说明评估a
不仅可行,而且语言规范保证 .C#表现得很好同样的方式。)