C++默认参数实现原理分析
简介定义
C++默认参数指的是当函数调用中省略了实参时自动使用的一个值。写法如下:
void foo(int a = 1)
{
}
void foo(int a, int b=1, int c=1)
{
}
默认参数有两个规则,
- 规则一:从第一个出现默认参数的参数开始,后面的参数必须也指定默认参数
void foo(int a=1, int b, int c=1); //错误
void foo(int a=1, int b, int c); //错误
void foo(int a, int b, int c=1); //正确
void foo(int a, int b=1, int c=1); //正确
void foo(int a=1, int b=1, int c=1); //正确
- 规则二:声明和定义分开时,仅声明处做初始赋值动作
void foo(int a = 1);
void foo(int a)
{
}
分析原理
在我的理解中,C++的各种特性基本是靠编译器隐藏了很多特殊操作,来实现这些特性,诸如面向对象等等。实际纯C语言结合一些编译器选项,完全可以实现C++的绝大多数效果。所以直接看汇编,扒开编译器隐藏的细节,到汇编这一层基本原形毕露,借助Compiler Explorer:
对比发现有没有默认参数两者汇编一模一样,那为什么可以实现不同的效果呢?再看下如果调用一下这2个函数:
可以看到如果不给默认参数赋值,则在调用处会由编译器自动给参数赋值为默认值,如果你指定了参数值,就用你指定的。也就是说编译器玩了个花招而已,并没多牛逼。
了解了实现原理后,再分析下为什么有上面的两个规则约束。假设带默认参数的函数可以这样定义:
int foo(int a = 1, int b = 1, int c);
那如下调用语句如何理解?:
//假设我的本意是a=1, b=2, c=3,则调用语句如下
foo(2,3);
//如果我现在想a=2, b=1, c=3,则调用语句如下
foo(2,3);
可以看到同样的调用会有两者意思,明显产生了歧义,再看如果默认参数按照规则一
定义:
int foo(int a, int b=1, c=1);
foo(2,3)//很明确,只有一个意思就是a=2,b=3,c=1
为什么是在申明处赋默认值?由默认参数的原理可知,默认参数是在调用处由编译器做赋值处理的,那么其他模块调用此有默认参数的函数在编译时需要通过头文件来获得默认参数值的信息,以便自己这个函数在编译时,对参数做默认值赋值。
默认参数值类型
默认参数可以是常量,全局变量,函数等