cout 堆栈,operator<< 运算符重载输出问题
在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<< 运算符重载输出问题的更多相关文章
- C++运算符重载详解
1.什么是运算符重载 运算符重载是一种函数重载. 运算符函数的格式:operatorop(argument-list)例如,operator+()重载+运算符.其中的op,必须是有效的C++运算符,如 ...
- C++:运算符重载函数之"++"、"--"、"[ ]"、"=="的应用
5.2.5 "++"和"--"的重载 对于前缀方式++ob,可以用运算符函数重载为: ob.operator++() //成员函数重载 或 operator++ ...
- C++之运算符重载(2)
上一节主要讲解了C++里运算符重载函数,在看了单目运算符(++)重载的示例后,也许有些朋友会问这样的问题.++自增运算符在C或C++中既可以放在操作数之前,也可以放在操作数之后,但是前置和后置的作用又 ...
- 玩转C++运算符重载
运算符重载语法:返回值类型 operator运算符(参数列表) { 代码逻辑... } C++中的运算符重载是通过函数来实现的,可以将重载的运算符看作是类成的一个成员函数,向普通函数一样调用.如重 ...
- [转]C++之运算符重载(2)
上一节主要讲解了C++里运算符重载函数,在看了单目运算符(++)重载的示例后,也许有些朋友会问这样的问题.++自增运算符在C或C++中既可以放在操作数之前,也可以放在操作数之后,但是前置和后置的作用又 ...
- C++多态性----运算符重载与虚函数
一.多态性 ①概述:多态是指同样的消息被不同类型的对象接收时导致的不同行为. ②类型: 可以分为四类:重载多态.强制多态.包含多态.参数多态. ------------------------ --- ...
- 《挑战30天C++入门极限》C++运算符重载转换运算符
C++运算符重载转换运算符 为什么需要转换运算符? 大家知道对于内置类型的数据我们可以通过强制转换符的使用来转换数据,例如(int)2.1f;自定义类也是类型,那么自定义类的对象在很多情况下也 ...
- 《挑战30天C++入门极限》C++运算符重载函数基础及其值返回状态
C++运算符重载函数基础及其值返回状态 运算符重载是C++的重要组成部分,它可以让程序更加的简单易懂,简单的运算符使用可以使复杂函数的理解更直观. 对于普通对象来说我们很自然的会频繁使用算数运 ...
- C++基本之 运算符重载
=====>友元运算符#include <iostream> using namespace std; class Test { public: Test(int a = 0) { ...
随机推荐
- Discuz3.1登录QQ互联显示redirect uri is illegal(100010)的解决
QQ互联最近也是BUG不断,引起了很多用户的不满,从早前关闭群组功能,到发布2.0接口标准,引发系列站长用户的连锁反应.而Discuz从X3开始,为了应对QQ互联的2.0接口标准,采用了云平台来整合Q ...
- vue-router 基本使用(vue工程化)
(1)概念: 路由,其实就是指向的意思,当我点击页面上的home按钮时,页面中就要显示home的内容,如果点击页面上的about 按钮,页面中就要显示about 的内容.Home按钮 => h ...
- 题解 P1967 货车运输
题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能 ...
- PS和AI安装后报代码为16的错误解决方法
1.问题 2.解决方式 右击属性,改为兼容性运行 参考文章地址:https://www.jb51.net/softjc/308950.html
- 【thinking in java】ArrayList源码分析
简介 ArrayList底层是数组实现的,可以自增扩容的数组,此外它是非线程安全的,一般多用于单线程环境下(Vector是线程安全的,所以ArrayList 性能相对Vector 会好些) Array ...
- Go:冒泡排序
package main import "fmt" func BubbleSort(arr *[5]int) { fmt.Println("排序前:", *ar ...
- SQL-如何使用 MongoDB和PyMongo。
先决条件 在开始之前,请确保已经安装了 PyMongo 发行版. 在 Python shell 中,下面的代码应该在不引发异常的情况下运行: >>> import pymongo 假 ...
- HTML基础知识 table中 th,td,tr
https://www.2cto.com/kf/201711/701872.html table是一个布局神器,之前看过很多代码,都是用table布局的.但是,我在学习的过程中,发现table有很迷的 ...
- [Oracle, MySQL] Oracle通过dblink连接MySQL
http://blog.csdn.net/dbanote/article/details/10488581 版权声明:本文为博主原创文章,未经博主允许不得转载. 业务上有这么一个需求,需要把Oracl ...
- android源码mm时的编译错误no ruler to make target `out/target/common/obj/JAVA_LIBRARIES/xxxx/javalib.jar', needed by `out/target/common/obj/APPS/xxxx_intermediates/classes-full-debug.jar'. Stop.
瞧见没有,就因为多了这一个反斜杠,浪费了一下午时间找问题,哭了~~~~