CPP {函数参数的入栈过程}

CPP {函数参数的入栈过程}

@LOC: 1

函数参数的入栈过程

定义

void F( int, int){}
int G( int _a){
    return _a;
}

F( G(1), G(2));

最先执行的是G(2), 然后才是G(1), 即函数参数的执行次序是 从右往左的;(很反直觉呀。。。 所以最好函数参数 不要写成函数调用)

性质

int Data = 0;
int F0(){ Data ++; return -1;}
int F1(){ Data += 100; return -2;}

void Func_0( int v0, int v1, int v2, int v3, int v4){ DE_(v0,v1,v2,v3,v4);}

void Func_1(){}
template< class _H, class... _T> void Func_1( const _H & _h, const _T & ... _t){ cout<< _h<< ","; if( sizeof...( _t) > 0){ Func_1( _t...);}}

Func_0( Data, F0(), Data, F1(), Data);的结果是: 101, -1, 100, -2, 0;
. 只要不是变长函数 其他函数包括模板函数 都是这个结果, 比如即使是模板函数 其实他的实例化 在编译期就完成了 本质上也属于普通函数;
Func_1( Data, F0(), Data, F1(), Data);的结果是: 101, -1, 101, -2, 101; (是不是很震惊…);
. 变长函数 很复杂, 他的实例化函数的类型是template<> Func_1< int, <int,int,int,int> > (很复杂把…);

虽然说 所有函数的参数的入栈(入程序栈, 程序的执行 本质上就是对程序栈的操作) 是从右往左的, 对于变长函数 他也不例外 但是他还是很特别的… 具体机制如下:

普通函数Func_0( Data, F0(), Data, F1(), Data):
参数*从右往左* 依次入栈:
0: Data(此时等于0)入栈, 即`v4==0`;
1: `auto ret=F1()` (即执行F1函数), 将ret入栈 即`v3==ret==-2`;
2: Data(此时等于100)入栈, 即`v2==100`;
3: `auto ret=F0()` (即执行F0函数), 将ret入栈 即`v1==ret==-1`;
4: Data(此时等于101)入栈, 即`v0==101`;

@DELI;

变长函数Func_1( Data, F0(), Data, F1(), Data): (这是我根据现象 反向猜测的)
0: 由于参数个数未知 首先得确定参数个数;
  0: *从左到右*递归的遍历所有参数[Data -> F0() -> ...] (遇到函数不执行 因为此时我们的目的 只是要确定参数个数);
  此时 我们计算出了*参数个数*;
  1: 在递归的回溯过程时 遇到*参数*为函数的 即`F1(),F0()`(注意次序) 执行该函数 且用其返回值来*替换*;
  此时 函数变成了*普通函数*: Func_1<int,int,int,int,int>( Data, ret_F0, Data, ret_F1, Data);
1: 执行普通函数`Func_1( Data, ret_F0, Data, ret_F1, Data);` (即参数从右往左入栈);
  0: Data(此时等于101)入栈, 即`v4==101`;
  1: ret_F1(此时等于-2)入栈, 即`v3==-2`;
  2: Data(此时等于101)入栈, 即`v2==101`;
  3: ret_F0(此时等于-1)入栈, 即`v1==-1`;
  4: Data(此时等于101)入栈, 即`v0==101`;

错误

@MARK: @LOC_0;
对于Func( D, F0(), D, F1(), D), 千万不要以为是: Func( D(最初值), F0(), D(受F0函数影响后), F1(), D(依次受[F0,F1]函数影响后));
. 无论是什么函数, 他的参数入栈 都是从右往左的!! 很容易犯这个错误, 以为是从左到右 依次生效的…

笔记

Func( D, F(), D, H(), D);
栈底[D, H(), D, F(), D], 也就是 F,H函数 不是在最一开始就执行的, 而是等入栈时遇到才执行!
也即是 千万不要以为: 第一个D值 是不受F/H函数影响的 这是错误的;
他的结果 正好与Func_0( vector<int>)Func_0( {D, F(), D, ...})的结果 相反, 从此可知 初始化列表的构造方式 是从左到右的;

但是如果Func是变长模板函数, 那么F,H函数 会在最一开始就执行, 且以H->F的顺序执行; 1,-1,1,-1,1 (跟变长宏无关 即与__VA__ARGS__无关, 也就是 DE_( D, H(), D, ...)Func( D, D(), D, ...)是完全一致的;
我认为他的底层是: 先倒序遍历一遍 目的是确定各个参数的类型, 即得到Func<int,int,....>类型 然后实例化, 变成普通函数 然后就执行普通函数的入栈过程;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值