Fork me on GitHub

C++函数重载与引用剖析

在介绍重载与引用之前,我们回顾以下C语言中函数,学过C语言我们都知道,定义一个函数可以给参数可以选择不给参数,这取决于我们调用这个函数时使用的功能,然而我们在C++中有一个叫缺省参数的概念。

缺省参数:声明或定义函数时为函数的参数指定一个默认值,在调用该函数时,如果没有指定实参则采用该默认值,否则使用指定的实参,并且,函数参数是从右开始匹配(printf函数就是从右向左压栈,打印的时候从左向右)

重载

首先:重载是在同一作用域内的几个函数名字相同,但形参列表不同,我们称之为函数的重载。例如以下:

1
2
3
void print();
void print(int a,int b);
void print(double a,double b);

这些函数接受参数类型不同,但是执行的操作非常相似,当我们调用这些函数的时候,编译器会根据我们传入的实参类型来自动匹配调用函数。

那么问题来了,在C语言中函数是否能进行重载吗?
毋庸置疑,答案是不行的,C语言中函数是不能进行重载的。这是为什么呢?让我们一探究竟。

从代码的编译到运行,在VC6.0或VS这种编译器下,它是系统直接完成了翻译与链接,直接生成了运行结果。
编译器内部完成了翻译部分:

1
2
3
4
5
6
7
1.预处理   
1)头文件展开
2)宏的替换
3)去注释
4)条件编译
2.编译过程:将高级语言转为汇编语言
3.汇编过程:汇编语言转为二进制程序

链接部分:所引用的数据链接进来
比如一个函数的声明如下:
void function(int x,int y);

在c语言中,编译器在编译后在库中的名字为_function
在c++中,编译器在编译后在库中的名字为_function_int_int

还有一个函数的声明如下:
void function(float x,float y);
在C语言中,编译器在编译后在库中的名字为_function
在c++ 中,编译器在编译后在库中的名字为_function_float_float
通过以上规律我们发现:
在链接时,都是找名字进行链接的,就比如以上两个函数,
在C语言中两个的名字一样,就会在链接中报错。
在c++ 中它们的名字不一样,所以就不会报错。
c++ 中函数名字的修饰规则,将参数的类型增加到最终的名字中,编译期间按照函数类型以及传入的参数类型将函数名修饰,如下

1
2
3
?@TestFunc@@YAAA@Z
?@TestFunc@@YANH@Z
?@TestFunc@@YHHH@Z

extern”C” 按照C来编译

当然,我们的main函数是不能被重载的啦

引用

有的人小时候因为名字太长或者叫起来不太方便就被起过小名或者绰号,这样方便其他人叫,那么我们的C++ 中的引用也是这样来定义引用的,是一个别名,也就是说,它是某个已存在变量的另一个名字。一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量。

引用创建及使用

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
int i;
double d;

int& r = i;
double& s = d;

i = 5;
cout<<"value of i:"<<i<<endl;
cout<<"value of reference:"<<r <<endl;

d = 3.14;
cout<<"value of d:"<<i<<endl;
cout<<"value of reference:"<<s <<endl;

上面的代码编译执行的结果如下:

value of i:5
value of reference:5
value of d:3.14
value of reference:3.14

当引用作为参数来传递参数时,我们如下使用:

1
2
3
4
5
6
7
8
9
10
11
12
void swap(int& a,int& b)
{
int temp = a;
a = b;
b = temp;
}
int a = 5;
int b = 6;
swap(a,b);

cout<<a<<endl;
cout<<b<<endl;

上面的代码执行运行的结果为6 5
我们知道,我们在C语言中交换两个变量使用指针来进行两个变量的交换,但上面的引用也完成了这样的功能,他们之间有何区别以及优缺点呢?

引用与指针的区别

先来说说引用底层实现原理
指针和引用在底层的处理方式完全一致,引用在底层就是按照指针来处理的
下面演变过程:

1
2
3
int a = 10;   
int& ra = a; -----> T* const
const int& cra = a; ----> const T* const

  • 相同点:
    都是地址的概。
    指针指向一块内存,它的内容是所指内存的地址;
    引用是某块内存的别名。
  • 不同的:
    1.指针是一个实体,而引用是一个别名
    2.引用使用无需解引用,指针使用时需要解引用
    3.引用只能在定义时被初始化一次,之后不可变;指针可变
    4.引用没有const,指针有const,const的指针不可变
    5.”sizeof引用”得到的是所指向的变量(对象)的大小,而”sizeof”指针”得到的是指针本身(所指向的变量或对象的地址)的大小
    6.指针可以为空,引用不能为空
    7.指针和引用自增(++)运算意义不一样

最需要注意的地方:当被问到函数传参有几种方式时,我们应该回答两种,值传递和址传递,但是你得分清楚,引用传递才是正真的址传递,而指针传递不是址传递,因为指针也是值,是一个地址但是本身也是一个指针变量值!!!
我们还需要注意:如果引用的方式作为函数的返回值类型,不能返回栈上的空间
返回的变量的生命周期一定要比函数的周期长
优缺点
使用引用的好处:
1.当传递一对象时,效率明显提高

2.安全

缺点:
1.使用时需要初始化

2.当引用一个指针时,指针置为空时非常危险

本文标题:C++函数重载与引用剖析

文章作者:LiuXiaoKun

发布时间:2018年11月11日 - 21:11

最后更新:2018年11月24日 - 20:11

原始链接:https://LiuZiQiao.github.io/2018/11/11/C++解析函数重载与引用剖析/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

0%