参数缺省,引用

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

(一)参数缺省:

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

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

看下边的一段代码:

#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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值