C++函数——引用reference

  • 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)//按照顺序从左往右传参
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值