博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
为什么C++函数形参默认值从最末一个赋值?
阅读量:7218 次
发布时间:2019-06-29

本文共 2328 字,大约阅读时间需要 7 分钟。

【1】函数调用时形参的压栈顺序

1、示例代码如下(VS2010):

1 #include 
2 using namespace std; 3 4 void fun(int a, int b, int c = 100); 5 6 void fun(int a, int b, int c) // 可以写 7 { 8 cout << "a :: " << a << endl; 9 cout << "b :: " << b << endl;10 cout << "c :: " << c << endl;11 }12 13 class A14 {15 public:16 void fun1(int a, int b);17 void fun2(int b, int c = 100);18 };19 20 void A::fun1(int a, int b = 100) // 这种情况可以写21 {22 }23 24 void A::fun2(int b, int c) // 这种情况下不可以写25 {26 }27 28 void main()29 {30 int n = 10;31 fun(n * n, n, n++);32 33 system("pause");34 }35 36 // run out:37 /*38 a :: 12139 b :: 1140 c :: 1041 请按任意键继续. . .42 */

分析:

从输出的结果琢磨,a如果等于10 * 10 = 100,说明是先压栈参数a。

然后,再压栈参数b,b = n, 那么b等于10。

最后,再压栈参数c,c = n++,即c等于10。而n最终等于11。

但是,还得用客观事实说明问题:

首先,压栈形参c,c = n++,即c等于10。而n执行完后等于11。

然后,压栈形参b,b = n,即b等于11。

最后,再压栈形参a,a = n * n, 即a等于121。

2、有人说还看得不太明白,云里雾里的。那么请再看如下实例分析。

代码如下:

1 #include 
2 using namespace std; 3 4 class TestA 5 { 6 public: 7 TestA(int a = 10, int b = 20, int c = 30, int d = 40) 8 : m_nA(a) 9 , m_nB(b)10 , m_nC(c)11 , m_nD(d)12 {}13 14 int getA() { cout << "TestA::getA() [" << m_nA << "]" << endl; return m_nA; }15 int getB() { cout << "TestA::getB() [" << m_nB << "]" << endl; return m_nB; }16 int getC() { cout << "TestA::getC() [" << m_nC << "]" << endl; return m_nC; }17 int getD() { cout << "TestA::getD() [" << m_nD << "]" << endl; return m_nD; }18 19 private:20 int m_nA;21 int m_nB;22 int m_nC;23 int m_nD;24 };25 26 int sumFunc(int a, int b, int c, int d)27 {28 return (a + b + c + d);29 }30 31 void main()32 {33 TestA aObj;34 cout << "调用顺序及求和结果如下:" << endl;35 cout << sumFunc(aObj.getA(), aObj.getB(), aObj.getC(), aObj.getD()) << endl;36 system("pause");37 }38 39 // run out:40 /*41 调用顺序及求和结果如下:42 TestA::getD()[40]43 TestA::getC()[30]44 TestA::getB()[20]45 TestA::getA()[10]46 10047 请按任意键继续. . .48 */

 通过调用全局函数sumFunc,分析其形参的压栈先后顺序。

【2】为什么函数形参默认值需要从最后一个赋值?

从上一步的研究结果发现:

函数调用时,首先压栈最后一个形参,若有一个已经确定默认值或常规调用可以忽略除非在特殊情况下才考虑的形参,那么置为最末一个形参。

建议在声明函数时,最好加上默认值。定义函数时,不需要再加默认值(因为编译器会报重定义默认参数值的编译错误)。

(备注:其实,声明不加定义加也行,但是为了便于代码的阅读与维护,建议声明加定义不加。)

反证法。假设不从最后一个赋默认值,那么试想一下,编译器就会匹配不到最后一个形参的值,报编译错误。

【3】总结

压栈形参由后向前,赋默认值也应由后向前。

 

Good Good Study, Day Day Up.

顺序 选择 循环 总结

转载地址:http://toqym.baihongyu.com/

你可能感兴趣的文章
Java 进制转换
查看>>
Code: UrlBuilder class in JavaScript
查看>>
[LintCode] Best Time to Buy and Sell Stock 买卖股票的最佳时间
查看>>
Android中文合集(5)(126+8篇)(chm格式)
查看>>
解读|百分点凭啥能推出「中国首个行业AI决策系统」
查看>>
Debian里编译内核
查看>>
WPF/E 我将怎么拥抱你?困惑与期待
查看>>
使用python玩跳一跳超详细使用教程
查看>>
js中push(),pop(),unshift(),shift()的用法
查看>>
WinForm界面开发之“OutLookBar”工具条
查看>>
iOS - OC NSDate 时间
查看>>
Netty重要概念介绍
查看>>
matcaffe的blob维度顺序
查看>>
之字形层次遍历二叉树
查看>>
一次查询性能提高40倍的经历
查看>>
ASP.NET MVC框架开发系列教程
查看>>
First Bad Version
查看>>
Sublimetext3将空格转换为Tab
查看>>
最全数据结构详述: List VS IEnumerable VS IQueryable VS ICollection VS IDictionary
查看>>
MySQL案例-初步恢复: alter引起的从库无限Crash
查看>>