在C++中cout的输出流其中,有一些问题非常easy出错,就比方以下这道简单程序。看似简单。但却是一个值得深思的问题~~

#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&lt;&lt; 运算符重载输出问题的更多相关文章

  1. C++运算符重载详解

    1.什么是运算符重载 运算符重载是一种函数重载. 运算符函数的格式:operatorop(argument-list)例如,operator+()重载+运算符.其中的op,必须是有效的C++运算符,如 ...

  2. C++:运算符重载函数之"++"、"--"、"[ ]"、"=="的应用

    5.2.5 "++"和"--"的重载 对于前缀方式++ob,可以用运算符函数重载为: ob.operator++() //成员函数重载 或 operator++ ...

  3. C++之运算符重载(2)

    上一节主要讲解了C++里运算符重载函数,在看了单目运算符(++)重载的示例后,也许有些朋友会问这样的问题.++自增运算符在C或C++中既可以放在操作数之前,也可以放在操作数之后,但是前置和后置的作用又 ...

  4. 玩转C++运算符重载

    运算符重载语法:返回值类型  operator运算符(参数列表) {  代码逻辑... } C++中的运算符重载是通过函数来实现的,可以将重载的运算符看作是类成的一个成员函数,向普通函数一样调用.如重 ...

  5. [转]C++之运算符重载(2)

    上一节主要讲解了C++里运算符重载函数,在看了单目运算符(++)重载的示例后,也许有些朋友会问这样的问题.++自增运算符在C或C++中既可以放在操作数之前,也可以放在操作数之后,但是前置和后置的作用又 ...

  6. C++多态性----运算符重载与虚函数

    一.多态性 ①概述:多态是指同样的消息被不同类型的对象接收时导致的不同行为. ②类型: 可以分为四类:重载多态.强制多态.包含多态.参数多态. ------------------------ --- ...

  7. 《挑战30天C++入门极限》C++运算符重载转换运算符

        C++运算符重载转换运算符 为什么需要转换运算符? 大家知道对于内置类型的数据我们可以通过强制转换符的使用来转换数据,例如(int)2.1f;自定义类也是类型,那么自定义类的对象在很多情况下也 ...

  8. 《挑战30天C++入门极限》C++运算符重载函数基础及其值返回状态

        C++运算符重载函数基础及其值返回状态 运算符重载是C++的重要组成部分,它可以让程序更加的简单易懂,简单的运算符使用可以使复杂函数的理解更直观. 对于普通对象来说我们很自然的会频繁使用算数运 ...

  9. C++基本之 运算符重载

    =====>友元运算符#include <iostream> using namespace std; class Test { public: Test(int a = 0) { ...

随机推荐

  1. Jmeter之断言——检查点

    Jmeter里的断言相当于lr中的检查点.用于检查测试中得到的响应数据等是否符合预期,用以保证性能测试过程中的数据交互与预期一致. 使用断言的目的:在request的返回层面增加一层判断机制:因为re ...

  2. 表单文件上传编码方式(enctype 属性)

    enctype 属性规定在发送到服务器之前应该如何对表单数据进行编码. 如下: <form action="upload.php" method="post&quo ...

  3. USB设备请求命令详解

    USB设备请求命令 :bmRequestType + bRequest + wValue + wIndex + wLength 编号 值  名称 (0) 0  GET_STATUS:用来返回特定接收者 ...

  4. UIWebView中javascript与Objective-C交互、获取摄像头

    UIWebView是iOS开发中常用的一个视图控件,多数情况下,它被用来显示HTML格式的内容. 支持的文档格式 除了HTML以外,UIWebView还支持iWork, Office等文档格式: Ex ...

  5. 浏览器通知js授权

    // 获得权限 Notification.requestPermission(); // 点击按钮 document.querySelector('#button').addEventListener ...

  6. 在git提交时忽略已提交过或从线上拉取下来但本地已修改的文件

    一.忽略: git update-index --assume-unchanged [file-path] 命令中的file-path 就是需要忽略提价的文件的路径 例子: git update-in ...

  7. Android Studio配置Esri ArcGIS

    1.Android Studio中新建项目: 2.打开project根目录下的build.gradle文件 repositories { jcenter() // Add the following ...

  8. 九度oj 题目1438:最小公倍数

    题目1438:最小公倍数 时间限制:1 秒 内存限制:128 兆 特殊判题:否 提交:2451 解决:2057 题目描述: 给定两个正整数,计算这两个数的最小公倍数. 输入: 输入包含多组测试数据,每 ...

  9. [POJ2774][codevs3160]Long Long Message

    [POJ2774][codevs3160]Long Long Message 试题描述 The little cat is majoring in physics in the capital of ...

  10. HDU 4944

    FSF’s game Problem Description FSF has programmed a game.In this game, players need to divide a rect ...