为了账号安全,请及时绑定邮箱和手机立即绑定

C++类的问题,输出结果

C++类的问题,输出结果

C++
hc茶 2018-04-09 17:10:44
//X.h class X{ public: int f1(); int f2(); protected:     int m;  }; //X.cpp int X::f1() { int m = 5; cout<<"f1: m = "<<m<<endl; return m;  }  int X::f2() { int m=3; cout<<"f2: m = "<<m<<endl; return m; } //main.cpp int main() {     X x;     cout<<x.f1()<<x.f2(); return 0; }为什么输出结果是f2: m = 3f1: m = 553而不是f1: m = 5f2: m = 353
查看完整描述

4 回答

已采纳
?
onemoo

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 吧...

查看完整回答
反对 回复 2018-04-10
  • hc茶
    hc茶
    tdm—gcc 4.9.2 64-bit debug 是这个吗?
  • onemoo
    onemoo
    gcc 4.9 最高只部分支持 C++14 标准。当然用来学习已经够了,事实上当前学 C++ 只要保证用 C++11 以上标准就可以了。
?
___C___

TA贡献168条经验 获得超109个赞

cout是先从右到左分别运行函数f2(),f1(),然后再输出两个函数的return返回值,谢谢采纳

查看完整回答
1 反对 回复 2018-04-09
?
慕设计7118955

TA贡献8条经验 获得超2个赞

cout输出将输出先像压栈一样保存在缓冲区,在进行输出,所以是先运行右边再左边

查看完整回答
反对 回复 2018-04-10
  • 4 回答
  • 1 关注
  • 1600 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信