- reference介绍
1、引用并非对象,只是为存在的对象起个别名。或者说引用是对指针的封装
2、引用只能绑定在对象上,布恩那个与字面值或者某个表达式的计算结果绑定在一起
3、引用必须初始化,所以使用引用之前不需要测试其有效性,故使用引用的效率会比指针高
4、引用更接近const指针,一旦与某个变量关联起来,将一直效忠于它
5、将引用变量作为参数时,函数将使用原始数据,而非副本
6、当数据所占内存比较大时,建议使用引用参数
7、函数传参只能引用单个元素,不能引用数组
8、函数返回值,一定不要返回局部变量的引用,因为局部变量会被系统回收,引用了也没办把用
9、函数可以不返回值,默认返回传入的引用对象本身
10、返回引用时,要求函数参数中包含被返回的引用对象
注意:强烈建议使用引用时,加上const
,禁止在引用的时候将数值(引用对象)修改了
- 引用参数的一些指导原则
1、能够修改调用函数的数据对象
2、数据的对象较大时,传递引用可以提高程序的运行效率
存在两种情况
(1)函数中不需要修改传递的参数:1)如果数据对象很小,建议使用按值传递。2)传递数组只能使用指针,并使用const关键字。3)较大的对象使用const指针或者引用以提高程序的运行效率。
(2)函数中需要修改传递的参数:1)数据对象是基本类型或者结构时,可以使用指针或者引用(基本类型建议使用指针)。2)数据对象是数组时,只能使用指针。3)数据类型时类时要求使用引用。
- 引用与指针的区别
1、指针是变量,可以重新赋值指向别的变量(地址)
2、引用在定义时必须初始化,并且不能再关联其他的变量
3、有空的指针,但是没有空的引用。(void 引用是不合法的)
//class1demo.hpp列举三种情况进行对比,分别是按值传递,指针传递,引用传递
#ifndef CLASS1DEMO_HPP_INCLUDED
#define CLASS1DEMO_HPP_INCLUDED
#endif // CLASS1DEMO_HPP_INCLUDED
#include <iostream>
using namespace std;
//声明函数
void sum1(int, int);
void sum2(int*, int*);
void sum3(int&, int&);
//定义函数
void sum1(int num1, int num2)
{
int res = 0;
res = num1 + num2;
cout << res << endl;
}
void sum2(int* ptr_num1, int* ptr_num2)
{
int res = 0;
res = *ptr_num1 + *ptr_num2;
cout << res << endl;
}
void sum3(int& num1, int& num2)
{
//cout << "sum3函数调用num1时值为: " << num1 <<endl;
int res = 0;
res = num1 + num2;
cout << res << endl;
}
//main.cpp
#include <iostream>
#include "class1demo.hpp"
using namespace std;
int main()
{
int num1 = 10;
int num2 = 20;
sum1(num1, num2);//按值传递的是副本,传递的值不会被修改
sum2(&num1, &num2);//指针方法传进去单个变量需要用取址符号
sum3(num1, num2);//引用传递的是原对象,传递的值不加const会被修改
return 0;
}
//程序输出
30
30
30
Process returned 0 (0x0) execution time : 0.153 s
Press any key to continue.
引用就是对指针
*
的封装,&
依旧是取址符号。把fact3函数改成下面的形式
inline void fact3(int& num1,int& num2)//定义引用函数
{
num1++;
num2++;
cout << "num1:" << "\t" << num1 << "\t" << "num2: " << "\t" << num2 << "\t" << endl;
cout << "&num1:" << "\t" << &num1 << "\t" << "&num2: " << "\t" << &num2 << "\t" << endl;
}
//程序输出
num1: 11 num2: 21
&num1: 0x66ff24 &num2: 0x66ff20
Process returned 0 (0x0) execution time : 0.092 s
Press any key to continue.
上面的代码存在的问题就是,你本身是在引用num1和num2,但是实际上却在函数的内部修改了,后面的程序在调用时会出现错误,所以强烈建议使用
const
inline void fact3(const int& num1,const int& num2)//定义引用函数
{
num1++;
num2++;
cout << "num1:" << "\t" << num1 << "\t" << "num2: " << "\t" << num2 << "\t" << endl;
cout << "&num1:" << "\t" << &num1 << "\t" << "&num2: " << "\t" << &num2 << "\t" << endl;
}
//程序会编译报错,禁止修改!!!
//下面尝试对数组尝试使用,这里为简单起见全部写入main文件
可以看到,即使是输入数组作为引用参数,但是输出的时候还是用的指针的方法才能得到数值。并且对于数组,引用不能使用const,这就失去了引用的初衷。故不建议引用数组
#include <iostream>
#include "inlinedemo.hpp"
using namespace std;
void fact5(int&);
void fact5(int(&re_nums)[3])//定义引用函数,并且对于数组不能使用const
{
for(int i = 0; i < 3; i++)
{
cout << " 取值: " << *(re_nums + i) << " 取址: " << re_nums + i << "\t";
}
}
int main()
{
int nums[] = {1,2,3};
fact5(nums);
return 0;
}
//程序输出
取值: 1 取址: 0x66ff10 取值: 2 取址: 0x66ff14 取值: 3 取址: 0x66ff18
Process returned 0 (0x0) execution time : 0.073 s
Press any key to continue.
另外对于返回引用,可以在函数的声明和定义的时候加上const,避免返回值被修改
const void fact5(const int&);//禁止引用传递和返回值引用传递被修改
const void fact5(const int& num1)
{
//定义函数
}
- 函数引用
C++有个神奇的机制就是可以给函数赋值
例如下面的函数,可以看到函数竟然被赋值了以后编译也不会报错,所以对函数的返回值进行const必不可少
#include <iostream>
#include "inlinedemo.hpp"
using namespace std;
int& sum(int);//声明函数
int& sum(int num)//返回引用类型的函数
{
num++;
return num;
}
int main()
{
int nums[] = {1,2,3};
int num1 = 10 ,num2 = 20;
int& result = sum(num1);//引用函数
cout << result << endl;
sum(num1) = 55;
cout << result << endl;
return 0;
}
/*
程序输出
11
55
Process returned 0 (0x0) execution time : 0.032 s
Press any key to continue.
*/
//正确的引用函数方法
const int& sum(int);//声明函数
const int& sum(int num)//返回引用类型的函数,函数定义
{
num++;
return num;
}
- 最后讲一下默认参数:就是直接在函数定义的时候就设置参数,
1、注意对于带此参数列表的函数,默认参数设置原则是必须从右往左添加默认参数
2、默认值可以在函数原型中或者定义中给出,不能在这两个位置同时出现。
void sample(int = 10);//或者void sample(int = num);这里不是将10赋值给int 而是一个占位符
void sample(int num)//void sample(int num = 10)
{
cout << num << endl;
}
int main()
{
sample();//默认打印10
sample(123);
}
//默认参数设置原则是必须从右往左添加默认参数
//因为在传参的时候不可能隔空传
void sample(int,int,string);//或者void sample(int = num);这里不是将10赋值给int 而是一个占位符
void sample(int num1, int num2 , string = "adai")
{
cout << endl;
}
//调用函数
sample(1,2)//按照顺序从左往右传参