参数缺省,引用

来源:互联网 发布:淘宝售后快捷短语话术 编辑:程序博客网 时间:2024/06/08 13:18

本篇文章将整理出关于参数缺省和引用的一些知识。

(一)参数缺省:

参数缺省包括全缺省和半缺省。顾名思义,全缺省就是函数的所有参数都给出默认值,半

缺省就是仅有函数的部分参数给出了默认值。

看下边的一段代码:

#include<iostream>using namespace std;int Add(int x, int y){return x + y;}int main(){int ret = Add();system("pause");return 0;}


要是写出上边的一段代码,低版本的vs会编译不通过,报错是Add函数不接收0个参数,

高版本vs会有红色标注。要是对于函数调用的时候不想给出参数,我们可以使用默认参

数,若将Add函数写成这样就好了:

int Add(int x = 0, int y = 0){return x + y;}


这就是所谓的全缺省。那么半缺省呢??继续实例:

int Add(int x , int y = 0){return x + y;}int main(){int ret = Add(10);system("pause");return 0;}


这样子的话,最后会得到10和0相加。当然调用的时候,我们也可以给出两个参数。如果

我们将x给出默认,y不默认,看可以不??

int Add(int x = 0 , int y){return x + y;}


要是Add函数写成上边这样,高版本vs编译器会红线报错:默认参数不在参数列表末尾。

想想这是为什么?其实,想一下就明白了,调用的时候(当然实参是只有一个)会把给

出的实参赋值给函数参数列表的第一个形参,肯定就不对了嘛。要是用更专业的说法解

释,本人认为:

函数参数入栈的时候是实参进入Add函数的栈帧,直接就当作第一个参数,所以~

总结:

使用半缺省,缺省的参数只能在参数列表的最后边。

缺省参数的用途:假如要传性别这个参数给函数,我们又约定缺省为男,所以,只需要

在需要传的性别是女时,给出参数。这就是缺省参数的用途。

(二)引用

引用就是给一个变量起一个别名。

比如:

int a = 10;int &ra = a;//ra是a的别名int &refa = a;//refa也是a的别名


总结:一个变量可以有多个别名。

     定义引用的时候必须初始化(指明定义的引用是哪个变量的别名)。

     引用只能在初始化的时候引用一次。

既然说,一个变量可以有多个别名,改变了别名的值,也就改变了变量的值,是不是感

觉引用就很不安全了??

其实并不是,如果不想改变,可以使用const修饰。

int a= 10;const int &ra = a;ra = 20;//报错!


关于const,在c中const修饰的变量是常变量,既有常量的属性,也有变量的属性。在c

++中,const修饰的变量就是常量。不可修改。

在学习指针的时候,如果一个函数的功能仅仅是打印或者是某个参数不可以被改变的时

候,我们可以用const修饰。在使用引用的时候也是一样的。

举例:

void print_a(const int &ra){ra = 20;//报错(左值必须是可以修改的)cout << ra << endl;}int main(){int a = 10;int &ra = a;print_a(a);system("pause");return 0;}


在cpp中,如果const修饰的是局部变量,则该局部变量是在栈里。不是不可以修改,可

以使用指针修改。

如果const修饰的是全局变量,不使用的时候是不会被分配空间的(&n是错误的),只有

在使用的时候也是有地址的。

const int n = 10;int main(){int a = 10;int &ra = a;int arr[n] = { 0 };//这里并不算使用n,此时的n仍相当于宏标识符const int *p = &n;//n才有空间,并且是只读区,不可修改的。system("pause");return 0;}

关于const引用的正确使用:看下边的几段代码:

const int n = 10;int &refn = a;


此时 refa是可以改变的,进而n的值可以改变。这就不对了嘛。(n是不可以改变的)。

使得n从安全变成不安全。

int m = 10;const int &refm = m;


这个就是正确的。使得m从不安全变得安全。

const int &refd= 5;


这个是正确的。const修饰的refd是一个常量的引用。

double d = 6.15;int &refd = d;


这个是不对的。要是这样就对了:

double d = 6.15;const int &refd = d;


为什么呢??由于引用的类型是int,变量的类型是double,所以此时就会用double类型

的d创建一个临时变量(也是d的隐式类型转换),refd引用的是临时变量。确切的说就

是临时常量。此时refd =6refd和d不在一个空间。

引用作为函数参数:

这里需要声明:引用的底层仍然是指针(这个可以通过汇编代码观到)。 

下边我们来测试传引用和传值得效率问题:

#include<iostream>#include<windows.h>using namespace std;struct BigData{int arr[100];};int getData(BigData bd){return bd.arr[0];}int main(){BigData bd = { 0 };int i = 0;int start = GetTickCount();for (i = 0;i < 100000000;i++){getData(bd);}int end = GetTickCount();cout << end - start << endl;system("pause");return 0;}


代码测试出的结果是6000毫秒左右。注意:每次运行的结果都不大一样,这根CPU的状态

有关。

当把上边代码改为传引用:效率可以提高大约一半,自己可以尝试。

引用作为函数的返回值:

看代码:

int& fun(){int num = 10;return num;}int main(){int &ret = fun();cout << ret << endl;system("pause");return 0;}


上边这段代码确实可以输出10.不过要是把上边的代码做以修改:

int& fun(){int num = 10;return num;}int main(){int &ret = fun();        printf("杨先生你好");cout << ret << endl;system("pause");return 0;}


看上边的代码,在高版本的vs下输出:

杨先生你好10

在低版本环境下ret的值会被改变。因为ret接收的是局部变量num,两者占用同一个空间

当num消失了,ret也就消失了,变成随机值。

高版本vs(比如vs2015)为什么ret的值一直是10,不知道做了什么优化。。哭

如果将上边的代码做以修改:

int& fun(){int num = 10;return num;}int main(){int ret = fun();printf("杨先生你好");cout << ret << endl;system("pause");return 0;}


这个ret的值不会改变。看原理:

后者的ret就不是引用了,保存的仅仅是num的值,所以不会随着num的消失而消失。

当引用作为函数的返回值的时候,有时会提高效率,有时并不会~~

我们知道,当函数的返回值,int或者double等等内置类型时,返回值是用寄存器带回

的。然而最大的寄存器也就32位,要是我们要返回一个比较大的结构体时,会使用引用

,引用不会创建临时变量,直接把需要带回的值赋值给接收返回值的变量。

总结:用函数的返回值的类型不是内置类型时,使用引用返回,会提高效率(减少创

      建临时对象)。

      当返回的是内置类型时,会用寄存器带回,跟使用引用返回的效率差不多。

引用和指针的区别:

1.指针在定义的时候可以不初始化,但是引用不行。

2.引用只能引用一个变量,而一般的指针变量并不是(除了const修饰的指针)

3.指针的大小仅与品台有关,而引用的大小与引用的对象的类型有关。

4.指针自加时,使得指针指向当前指向空间的下一个空间;引用自加时,会使自身和它

所引用的对象的值加1.

5.引用比指针更安全。(使用指针时,一定要检查指针的值是否是NULL)


越努力,越幸运~~



1 0
原创粉丝点击