为什么C++函数形参默认值从最末一个赋值?
【1】函数调用时形参的压栈顺序
1、示例代码如下(VS2010):
#include <iostream>
using namespace std; void fun(int a, int b, int c = ); void fun(int a, int b, int c) // 这种情况不可以写,因为函数声明已写
{
cout << "a :: " << a << endl;
cout << "b :: " << b << endl;
cout << "c :: " << c << endl;
} class A
{
public:
void fun1(int a, int b);
void fun2(int b, int c = );
}; void A::fun1(int a, int b = ) // 这种情况可以写
{
} void A::fun2(int b, int c) // 这种情况下不可以写,因为函数声明已写
{
} void main()
{
int n = ;
fun(n * n, n, n++); system("pause");
} // run out:
/*
a :: 121
b :: 11
c :: 10
请按任意键继续. . .
*/
分析:
从输出的结果琢磨,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、有人说还看得不太明白,云里雾里的。那么请再看如下实例分析。
代码如下:
#include <iostream>
using namespace std; class TestA
{
public:
TestA(int a = , int b = , int c = , int d = )
: m_nA(a)
, m_nB(b)
, m_nC(c)
, m_nD(d)
{} int getA() { cout << "TestA::getA() [" << m_nA << "]" << endl; return m_nA; }
int getB() { cout << "TestA::getB() [" << m_nB << "]" << endl; return m_nB; }
int getC() { cout << "TestA::getC() [" << m_nC << "]" << endl; return m_nC; }
int getD() { cout << "TestA::getD() [" << m_nD << "]" << endl; return m_nD; } private:
int m_nA;
int m_nB;
int m_nC;
int m_nD;
}; int sumFunc(int a, int b, int c, int d)
{
return (a + b + c + d);
} void main()
{
TestA aObj;
cout << "调用顺序及求和结果如下:" << endl;
cout << sumFunc(aObj.getA(), aObj.getB(), aObj.getC(), aObj.getD()) << endl;
system("pause");
} // run out:
/*
调用顺序及求和结果如下:
TestA::getD()[40]
TestA::getC()[30]
TestA::getB()[20]
TestA::getA()[10]
100
请按任意键继续. . .
*/
通过调用全局函数sumFunc,分析其形参的压栈先后顺序。
【2】为什么函数形参默认值需要从最后一个赋值?
从上一步的研究结果发现:
函数调用时,首先压栈最后一个形参,若有一个已经确定默认值或常规调用可以忽略除非在特殊情况下才考虑的形参,那么置为最末一个形参。
建议在声明函数时,最好加上默认值。定义函数时,不需要再加默认值(因为编译器会报重定义默认参数值的编译错误)。
(备注:其实,声明不加定义加也行,但是为了便于代码的阅读与维护,建议声明加定义不加。)
反证法。假设不从最后一个赋默认值,那么试想一下,编译器就会匹配不到最后一个形参的值,报编译错误。
【3】总结
压栈形参由后向前,赋默认值也应由后向前。
Good Good Study, Day Day Up.
顺序 选择 循环 总结
为什么C++函数形参默认值从最末一个赋值?的更多相关文章
- ES6学习 --函数参数默认值与解构赋值默认值
1. ES6的解构ES6中引入了解构赋值的操作,其作用是:将值从数组Array或属性从对象Object提取到不同的变量中 即分为两种情况:从数组Array中解构,以及从对象Object中解构 ①.从数 ...
- ES6函数参数默认值作用域的模拟原理实现与个人的一些推测
一.函数参数默认值中模糊的独立作用域 我在ES6入门学习函数拓展这一篇博客中有记录,当函数的参数使用默认值时,参数会在初始化过程中产生一个独立的作用域,初始化完成作用域会消失:如果不使用参数默认值,不 ...
- 函数的默认值与动态参数arguments的总结
在js函数与作用域,了解函数基本概念中,我们发现当函数的实参有一个没有上传的时候,对应的形参time展示的值就是undefined,如下代码所示: <!DOCTYPE html> < ...
- 【C#基础概念】函数参数默认值和指定传参和方法参数
函数参数默认值和指定传参 最近在编写代码时发现介绍C#参数默认值不能像PL/SQL那样直接设置default,网上也没有太多详细的资料,自己琢磨并试验后整理成果如下: C#允许在函数声明部分定义默认值 ...
- 问题:C++形参默认值为什么一定要放在最后?
问题:C++形参默认值为什么一定要放在最后? 1.会出现歧义! 2.从汇编角度看是怎么回事? 待解答!!
- Python函数参数默认值的陷阱和原理深究"
本文将介绍使用mutable对象作为Python函数参数默认值潜在的危害,以及其实现原理和设计目的 本博客已经迁移至: http://cenalulu.github.io/ 本篇博文已经迁移,阅读全文 ...
- java函数参数默认值
java函数参数默认值 今天,需要设定java函数参数的默认值,发现按照其它语言中的方法行不通 java中似乎只能通过函数的重载来实现 函数参数默认代码
- Python函数参数默认值的陷阱和原理深究(转)
add by zhj: 在Python文档中清楚的说明了默认参数是怎么工作的,如下 "Default parameter values are evaluated when the func ...
- php函数指定默认值的方法
发布:JB02 来源:脚本学堂 [大 中 小] 本文介绍下,在php编程中,指定函数的默认值的方法,分享二个例子,供大家学习参考下.本文转自:http://www.jbxue.com/ar ...
随机推荐
- /etc/passwd- 和/etc/shadow-文件
今天偶尔看到系统里有/etc/passwd- 和/etc/shadow-文件,经测试只要执行过系统的用户操作命令就会产生,如deluser.passwd.chpasswd.adduser等命令,应该是 ...
- 关于byte[]与string、Image转换
byte[]与string转换 参考网址:https://www.cnblogs.com/xskblog/p/6179689.html 1.使用System.Text.Encoding.Default ...
- js禁用页面上右键菜单、选中和复制
有时候我们不想页面上的内容被人复制走,那么就可以使用js对页面进行设置,禁止右键菜单.禁止选中.禁止复制等功能可以有效的达到这个效果,js代码如下所示: /** * 禁用右键菜单 */ documen ...
- oracle稳定执行计划(更改)的方法
应用于那些执行计划已经发生了的不好的变更的SQL上(在不改变SQL文本的情况下,改变其执行计划),即便通过创建SQL Profile解决了目标SQL执行计划变更的问题,依然不能保证系统后续执行的SQL ...
- php中$this->的用法简单介绍
php中我们一般是先声明一个类,然后用这个类去实例化对象!$this 的含义是表示实例化后的具体对象!$this->表示在类本身内部使用本类的属性或者方法.‘->’符号是“插入式解引用操作 ...
- [Android][Android Studio] Gradle项目中加入JNI生成文件(.so文件)
版权声明:本文作者:Qiujuer https://github.com/qiujuer; 转载请注明出处,盗版必究! ! ! https://blog.csdn.net/qiujuer/articl ...
- 20170929 微信小程序项目开发
1. 微信小程序环境搭建 请参考官网,哈哈! 2. 微信小程序基础学习 文件结构: 3. 微信小程序实战 4. 目前的逻辑,是从微信小程序的界面和服务器的Web API 进行交互, 有个注意事项就是W ...
- double类型相减有小数误差
如 :19.9-9.9=9.9999999999999,而不是10double相减会转换成二进制,因double有效位数为 16位这就会出现存储小数位数不够的情况,这种情况下就会出现误差 //两个Do ...
- 装系统w7、ubuntu、centos等系统(一)
装w7系统准备 1.从老毛桃u盘启动盘制作工具_老毛桃u盘装系统_老毛桃pe_老毛桃官网下载装机版 2.一个正常使用的U盘,但容量大于4G,并且插入电脑保持连接 3.老毛桃装机版选择U盘启动-> ...
- sap 查看自己代码的结构
1:进入系统X3C:然后输入T-CODE bsp_wd_cmpwb