首页 > 代码库 > cout 堆栈,operator<< 运算符重载输出问题

cout 堆栈,operator<< 运算符重载输出问题

在C++中cout的输出流当中,有一些问题很容易出错,就比如下面这道简单程序,看似简单,但却是一个值得深思的问题~~

#include <iostream>

using namespace std;


int foo(int &x)
{
      cout << "第" << x << "次调用" << " ";
      return ++x;
}

int main()
{
      int i = 1;
      cout << foo(i) << ‘\t‘ << foo(i) << endl;

}


很多人一开始会以为输出的结果会是:

第1次调用 2 第2次调用 3


但是结果却是:

第1次调用 第2次调用 3 2


为什么嘞??? 首先需要了解的是:


进程空间:

代码区----------------存放程序的执行代码
全局数据区------------存放全局数据,常量,文字量,静态全局量和静态局部量
堆区------------------存放动态内存,供程序随机申请使用
栈区------------------函数数据区(局部数据区)
(以上是运行中的内存布局)


函数调用的整个过程就是栈空间操作的过程。函数调用时,C++作以下工作:
(1)建立被调函数的栈空间,其大小由函数定义体中的数据量决定;
(2)保护调用函数的运行状态和返回地址;
(3)传递参数;
(4)将控制权转交给被调函数;
(5)函数运行完成后,复制返回植到函数局部数据块底部;
(6)恢复被调函数的运行状态;
(7)返回调用函数。

调用一个函数可以看作是一个栈中元素的压栈与退栈操作。


有了以上的介绍,解释过程就能知道了:

原始输出语句: cout << foo(i) << ‘\t‘ << foo(i) << endl;

cout输出的执行顺序是从右向左执行的,so:

1:执行<<endl,因为没有std::cout对象,无法执行,压栈

2:执行<<foo(i),执行foo(1),输出:第1次调用,得到返回值2,还是因为没有std::cout对象,无法马上输出,压栈
此时,代码变成cout << foo(i) << ‘\t‘ << 2 << endl;

3:执行<< ‘\t‘ ,没有std::cout对象,无法马上输出,压栈
此时,代码变成cout << foo(i) << ‘\t‘ << 2 << endl;

4:执行<<foo(i),执行foo(2),输出:第2次调用 得到返回值3,还是因为没有std::cout对象,无法马上输出,压栈
此时,代码变成cout << 3 << ‘\t‘ << 2 << endl;


对于以上过程还需注意两点:

1. 【int& x】 也就是说 x实际上是i的别名

2. cout << foo(i) << ‘\t‘ << foo(i) << endl;
<==> operator << (cout, foo(i)的返回值, ‘\t‘, foo(i)的返回值, endl); 参数从右到左压入堆栈区:


cout 堆栈,operator<< 运算符重载输出问题