先看下以下代码

#include<iostream>
using namespace std; int x = ; int f1()
{
x = ;
return x;
} int f2()
{
x = ;
return x;
} int main()
{
//Test1
cout << x << ' ' << f1() << ' ' << f2() << endl; //2 2 3 //Test2
int i = ; cout << i++ << ' ' << i << ' ' << ++i << endl; //1 2 2 //Test3
int s[] = {, , }; int *p = s; //cout << *p << ' ' << *(p++) << ' ' << *(++p) << endl; //3 2 3 //cout << *p++ << ' ' << *++p << ' ' << *p << endl; //2 3 3 //cout << *p << ' ' << *++p << ' ' << *p << endl; //2 2 2 //cout << *++p << ' ' << *p << ' ' << *++p << endl; //3 3 3 //cout << *p++ << ' ' << *p << ' ' << *p++ << endl; //2 3 1 //cout << *p << " " << *p++ << " " << *p << endl;//2 1 2
}
  1. 首先先明白运算符重载:

    ostream & operator <<(ostream &stream, T &t)

    返回的是一个ostream类型的引用,为什么要返回引用,先留着待会说。

  2. 然后,cout是什么,是一个ostream类的对象
  3. 接着,cout<<a;的实质是cout对象调用其成员函数operator<<(),即cout.operator<<(a),返回一个ostream类型的引用
  4. 那么cout << a << f();其实就是cout.operator<<(a).operator<<(f())。(可以把cout.operator<<(a)看成一个新的cout)
  5. 问题来了,cout是从右到左读取参数,如果参数是函数,则先执行函数体,再将返回的值压栈,否则直接将压栈,最后再将栈中的值输出来(见上述例子的第一个输出)
  6. 如果涉及i++和++i呢,问题就变得更加复杂。因为不同的编译器有不同的输出结果啊!这里选的是vs2013。这里先要明白什么是i++和++i
    T operator ++()                    //++var
    {
    var = var+;
    return var;
    }
    T operator ++(int dummy) //var++(dummy)
    {
    T tmp = var;
    var = var+;
    return tmp;
    }

    可以看到,++i比i++更有效率(少了一句T tmp=var;)

  7. 那么同样,cout是从右到左读取参数,若遇到i++,则立即将i的压栈(注意是值,而不是i的引用),再执行i+1;若遇到++i,则先执行i+1,再将i的引用压栈(而不是i的值,是引用!!!);若遇到i,则将i的引用压栈。
  8. 最后一个问题,为什么
    ostream & operator <<(ostream &stream, T &t)

    要返回一个引用类型呢?如果不返回引用类型而是返回一个ostream对象的话,那么cout << a << b这样的式子就会有问题,编译不会通过的,因为cout<<a返回了一个ostream的对象,而这个对象是一个“值”,而不是一个“变量”,它不能作为左值。(比如a = 1是正确的,而1 = 1是错误的,因为1是一个值,而不是变量,不能作为左值)。

  9. 至此,上面的代码为什么会输出这些奇怪的结果就一目了然了,值得吐槽的一点是,这些跟编译器有关,研究起来很没意思,Anyway,搞清楚了还是挺开心的^^

cout顺序,i++和++i的更多相关文章

  1. c++顺序表基本功能

    头文件 #define LIST_MAX_SIZE 5#define LISTINCREMENT 2#include<assert.h>#include<string>temp ...

  2. C++中如何建立一个顺序表

    准备数据 #define MAXLEN 100 //定义顺序表的最大长度 struct DATA { char key[10]; //结点的关键字 char name[20]; int age; }; ...

  3. C++ 数据结构学习一(顺序表)

    //SequentialList.h 顺序表模板类 #ifndef SEQUENTIAL_LIST_HXX#define SEQUENTIAL_LIST_HXX using std::cout; us ...

  4. 数据结构C++实现代码-顺序表

    参考:https://blog.csdn.net/ebowtang/article/details/43094041 //seqList.h// //包含顺序表中的声明// #include<i ...

  5. 线性表之顺序表C++实现

    线性表之顺序表 一.头文件:SeqList.h //顺序线性表的头文件 #include<iostream> ; //定义顺序表SeqList的模板类 template<class ...

  6. C++实现顺序查找,折半查找,插值查找

    1.顺序查找 从数组起始扫描到数组结尾,判断该索引数组是否和关键字相等,成功返回1 代码如下: //顺序查找 int seqSearch(int *array, int low, int high, ...

  7. STL之set(唯一且有顺序)

    set作为一个容器也是用来存储同一数据类型的数据类型,并且能从一个数据集合中取出数据, 在set中每个元素的值都唯一,而且系统能根据元素的值自动进行排序.应该注意的是set中数元素的值不能直接被改变. ...

  8. 数据结构实验1:C++实现静态顺序表类

    写了3个多小时,还是太慢了.太菜了! 图1 程序运行演示截图1 实验1 1.1 实验目的 熟练掌握线性表的顺序存储结构. 熟练掌握顺序表的有关算法设计. 根据具体问题的需要,设计出合理的表示数据的顺序 ...

  9. C++顺序表(模板总结)

    C++顺序表(模板总结) 总结: 1.模板类的实质是什么:让程序员写出和类型无关的代码 2.模板的对象时什么:方法或者类 3.是对类中的一系列操作,提供一个不固定数据类型的方法 用模板做的类的时候要指 ...

随机推荐

  1. 算法笔记_076:蓝桥杯练习 结点选择(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 有一棵 n 个节点的树,树上每个节点都有一个正整数权值.如果一个点被选择了,那么在树上和它相邻的点都不能被选择.求选出的点的权值和最大是多 ...

  2. python——修饰符

    修饰符基础--闭包 什么是闭包呢?标准的概念大家可以看wikipedia上的解释 举个例子: def do_add(base): def add(increase): return base + in ...

  3. DOM BOM document window 区别

    DOM 是为了操作文档出现的 API,document 是其的一个对象: BOM 是为了操作浏览器出现的 API,window 是其的一个对象.   使用下图讲解:   归DOM管的: E区:即doc ...

  4. hibernate list和iterate

    list方法会一次查出所有内容,放在list里和缓存中.再次查询同一内容仍然会去数据库重新查一遍,并刷新缓存. iterate方法会一次查出所有内容的ID,等用到某个ID对应的内容时又会去根据主键查询 ...

  5. ECS 实例网络带宽

    1. 带宽是否独享? 是独享. 2. 带宽单线还是双线,电信还是网通? 多线 BGP(中国电信.联通.移动.教育网等)接入,确保全国用户访问畅通. 3. 5 Mbps 带宽怎么理解? 5 Mbps 带 ...

  6. android的五大布局(layout)

    Android的界面是有布局和组件协同完成的,布局好比是建筑里的框架,而组件则相当于建 筑里的砖瓦.组件按照布局的要求依次排列,就组成了用户所看见的界面.Android的五大布局分别是LinearLa ...

  7. bootstrap 学习笔记 轮播(Carousel)插件

    Bootstrap轮播(carousel)插件是一种灵活的响应式的向站点添加滑块的方式.除些之外,内容也是足够灵活的,可以是图像,内嵌框架,视频或者其他您想要旋转的任何类型的内容. 示例: 下面是不念 ...

  8. ajax跨域--jsop方法

    1.什么是JSONP? 要了解JSONP,不得不提一下JSON,那么什么是json ? json简单说就是javascript中的对象和数组,所以这两种结构就是对象和数组两种结构,通过这两种结构可以表 ...

  9. unity, break prefab instance

    菜单->GameObject->Break Prefab Instance,可以打断prefab实例与prefab的连接. 一个用处是:比如想从sceneA拷贝一部分Hierarchy结构 ...

  10. unity, iterate immediate children and iterate all children

    遍历所有直接子节点(immediate children): foreach (Transform child in transform) { // do whatever you want with ...