为了解释这里发生了什么,让我们让事情变得更简单:cout<<2*2+1*1;
. 首先会发生什么,2*2 还是 1*1?一个可能的答案是 2*2 应该首先发生,因为它是最左边的事情。但是 C++ 标准说:谁在乎?!毕竟,无论哪种方式,结果都是 5。但有时它很重要。例如,如果f
和g
是两个函数,而我们是f()+g()
,则不能保证哪个会先被调用。如果f
打印了一条消息,但g
退出了程序,则该消息可能永远不会被打印。在您的情况下,i[2]
之前被调用过i[0]
,因为 C++ 认为这无关紧要。你有两个选择:
一种选择是更改您的代码,这样就没有关系了。重写您的[]
运算符,使其不会更改Int
, 而是返回一个新的Int
。无论如何,这可能是一个好主意,因为这将使它与[]
地球上所有其他运营商的 99% 保持一致。它还需要更少的代码:
Int &operator[](int x) { return this->v + x;}
.
您的另一个选择是保持[]
不变,并将您的打印分成两个语句:
cout<<i[0]; cout<<i[2];
某些语言实际上确实保证 in 2*2+1*1
,首先完成 2*2 。但不是 C++。
编辑:我并不像我希望的那样清楚。让我们慢慢尝试。C++ 有两种评估2*2+1*1
.
方法一:2*2+1*1 ---> 4+1*1 ---> 4+1 --->5
。
方法二:2*2+1*1 ---> 2*2+1 ---> 4+1 --->5
。
在这两种情况下,我们都会得到相同的答案。
让我们用不同的表达式再试一次:i[0]+i[2]
.
方法一:i[0]+i[2] ---> 2+i[2] ---> 2+4 ---> 6
。
方法二:i[0]+i[2] ---> i[0]+4 ---> 4+4 ---> 8
。
我们得到了不同的答案,因为它[]
有副作用,所以不管是先做i[0]
还是先做都很重要i[2]
。根据 C++,这些都是有效的答案。现在,我们已准备好解决您最初的问题。您很快就会看到,它几乎与操作员无关<<
。
C++是如何处理的cout << i[0] << i[2]
?和以前一样,有两种选择。
方法一:cout << i[0] << i[2] ---> cout << 2 << i[2] ---> cout << 2 << 4
。
方法二:cout << i[0] << i[2] ---> cout << i[0] << 4 ---> cout << 4 << 4
。
第一种方法将像您预期的那样打印 24 。但是根据 C++,方法 2 同样好,它会像你看到的那样打印 44。请注意,问题发生在<<
被调用之前。没有办法超载<<
来防止这种情况,因为到时间<<
运行时,“损坏”已经造成。