4 回答
TA贡献883条经验 获得超454个赞
其实这两种结果都有可能出现。
先明确一下关于运算符和操作数的基本知识:运算符需要有操作数才能构成表达式(比如 a + b 就是一个加法表达式,+ 是运算符,a 和 b 就是操作数)。而运算符表达式在执行时有一个“操作数求值”的过程(也就是确定 a 和 b 的值)。
如果操作数本身是个函数调用,那么对这个操作数求值就是得到函数的返回值。有一点很重要:函数中的一些代码(尤其是 cout << 这样的IO操作)的行为算是函数的副作用,这些副作用的发生并不一定和求值同时发生。
关于表达式的副作用何时发生,C++ 其实有比较复杂的序列点规则。我不打算细说这个规则,后面遇到具体情况时我会提到它,你目前只需要记住副作用不一定和求值同时发生。
那么我用你的这个例子具体说明一下:
cout<<x.f1()<<x.f2() 这是一个复合表达式。
对其中的 cout << x.f1() 这个子表达式来说 x.f1() 是右操作数,这个右操作数是个函数调用。
而 << 其实也是函数调用,这是重载 << 运算符函数。x.f1() 其实算是 << 函数的参数。
cout<<x.f1()<<x.f2() 其实是连续两次 << 调用,并且是 <<x.f1() 在前,<<x.f2() 在后(运算符的优先级决定的)。也就是说一定是先调用了 << 5,再调用 << 3,所以最后结果是 53(5在3之前)。
至于让你疑惑的那部份输出:C++ 的求值和序列点规则说“参数的副作用要在函数执行前发生”。注意:只是在之前发生即可。
所以完全有可能 f1() 和 f2() 的副作用(也就是输出"f1: m = 5"和"f2: m = 3")在两次 << 函数调用前就已经发生了。加之 C++ 没有规定参数副作用谁先谁后,所以"f2: m = 3"先输出是有可能的。
====以上就是关于你看到的这个结果的解释====
下面我想多说下:
我不知道你用的编译环境是什么? 编译器遵循的是哪个标准?
实际上如果你用的编译器支持的 C++ 标准够新的话(C++17),f1: m = 5 和 5 是会先输出的。
这是因为在 C++17 标准中增加了一些序列点规则,导致这个代码的行为不再是不确定的,而是保证会先输出 f1: m = 5 和 5。
(我有些好奇不同编译器在各个标准下的行为,希望能告知我你用的编译环境是什么)
最后,你知道你其实根本就没用到 X 的成员变量 m 吧...
- 4 回答
- 1 关注
- 1727 浏览
添加回答
举报