为什么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 ...
随机推荐
- Java+selenium 如何下拉移动滚动条【实战】
一.场景:在编写脚本过程中需要定位的元素,在界面的底部,需要拖拽下拉滚动条,再进行定位元素. 实现思路:用Selenium 里面的 scrollTo 方法实现 二.脚本示例: 1. 用例设计 @The ...
- java JDBC (四)
package cn.sasa.demo4; import java.sql.Connection; import java.sql.PreparedStatement; import java.sq ...
- java 线程 (二) 线程池
package cn.sasa.demo2; import java.util.concurrent.ExecutorService; import java.util.concurrent.Exec ...
- 洛谷P3234 抄卡组 [HNOI2014] 字符串hash
正解:字符串hash 解题报告: 传送门! 字符串hash是字符串匹配中很常见的一个方法,原理也很好懂,这里就不做太多阐述辣有时间放到hash笔记里面去QAQ 题意不说了挺好理解的,自带一句话概括好评 ...
- Python中Mock的示例(转)
原文:https://segmentfault.com/a/1190000008753754 一些常用的mock示例 先简单定义个类,方便举例: class Person: def __init__( ...
- 二、Spring Boot 配置文件
1.配置文件 Spring Boot使用一个全局的配置文件,配置文件名是固定的 application.properties applicatioin.yml 配置文件的作用:修改Spring Boo ...
- SpringBoot-整合@transactional注解
springboot默认集成事务,只主要在方法上加上@Transactional即可
- 如何让帝国CMS7.2搜索模板支持动态标签调用
帝国cms站内搜索一般不支持动态标签调用,如果要调用如何实现呢?修改两个地方就可以实现了.打开 /e/search/result/index.php 文件,找到(文件改了,不会调用也是徒劳!看看这个帝 ...
- 报错解决——Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX AVX2
在导入tensorflow后,进行运算时,出现了报错Your CPU supports instructions that this TensorFlow binary was not compile ...
- abp中linq的应用
private IQueryable<MembershipEntity> SelectOrScrrenMember(GetMemberInput input) { string[] use ...