C++入门(引用&内联函数)

引用

引用的概念

引用不是定义一个变量,而是给已存在的变量取了一个别名。编译器不会为引用变量开辟内存空间,它和它的引用的变量共用一块内存空间
比如:你有你的名字,在家的时候爸爸妈妈可能会叫你的小名,当然你还是你,只是有不同的名字。
在这里插入图片描述

引用的语法是:
类型& 引用变量名(对象名) = 引用实体;

void test()
{
	int a = 10;
	int& ra = a;

	printf("a = %d\n", a);
	
	printf("ra = %d\n", ra);
}

我们运行的结果就是:
在这里插入图片描述
这里我们需要注意的是:引用类型必须和引用实体是同种类型

引用的注意事项

我们可以不不进行地址传递而交换实参的值

void Swap(int& a, int& b)
{
	int temp = a;
	a = b;
	b = temp;
}

在这里我们发现引用和指针一样都可以改变实参的值,那引用能不能替代指针呢?
答案是不行的!!!
为什么呢?

1.引用必须初始化

1.我们来看下面这段代码:

int main()
{
	int a = 10;

	int& b;

	return 0;

我们不知道要给谁取别名,能不能先不给引用初始化呢?
当然不行,这就是我们要说的第一点引用必须 初始化

2.引用在初始化后不可改变

下面这行代码中操作b = c; 是c赋值给b ,还是b变成c的别名呢?

int main()
{
	int a = 10;
	int& b = a;;

	int c = 20;

	//下面这行代码是c赋值给b ,还是b变成c的别名呢?
	b = c;

	return 0;
}

运行一下我们看看结果如何
在这里插入图片描述
在这里插入图片描述

在这里我们可以看到上述操作仅仅只是赋值操作;所以说引用不可以替代指针

3.一个变量可以有多个引用

int main()
{
	int a = 10;
	
	//一个对象可以有多个别名,可以给别名继续取别名
	int& b = a;
	int& c = a;

	int& d = c;

	return 0;
}

我们总结一下:
1.引用必须初始化
2.引用在初始化后不可以改变
3.一个变量可以有多个引用

引用的使用场景

1.做参数

在开头我们提到了交换函数,那么我们来看看通过不同的传参实现交换函数
看一下下面这段代码

//1.值传递
void mySwap01(int a, int b)
{
    int temp = a;
    a = b;
    b = temp;
}
//2.地址传递
void mySwap02(int* a, int* b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}
//3.引用传递
void mySwap03(int &a , int &b)
{
    int temp = a;
    a = b;
    b = temp;
}

很明显我们可以看出后两个函数都实现了交换函数,第一个函数形参a , b 的值发生了交换,但没有交换实参的值。
引用传递中形参是实参的引用,指向同一块空间,所以实参也跟着发生了改变。

2.引用做函数的返回值

#include<iostream>
using namespace std;
//1.不要返回局部变量的引用
int& test01()
{
	int a = 10;   //局部变量存放在四区的  栈区
	return a;
}
//2.函数的调用可以作为左值
int& test02()
{
	static int a = 10;  //静态变量,存放在全局区,全局区上的数据在程序结束后系统释放
	return a;
}

int main()
{
	int& ref = test01();
	cout << "ref = " << ref << endl;   //第一次结果正确,
	cout << "ref = " << ref << endl;
	int& ref2 = test02();
	cout << "ref2 = " << ref2 << endl;   //输出10
	cout << "ref2 = " << ref2 << endl;   //输出10

	test02() = 1000;   //如果函数的返回值是引用,这个函数可以作为左值
	cout << "ref2 = " << ref2 << endl;     //输出1000
	cout << "ref2 = " << ref2 << endl;     //输出1000
	return 0;
}

我们来看一下上述代码的运行结果:
在这里插入图片描述

不要返回局部变量的引用

我们看到在调用完 test01() 后第一次输出的结果正确,第二次输出的结果错误,这是为什么呢?
在test01 () 中 a 是局部变量存放在栈区,当函数调用完成后自动销毁,第一次打印成功是编译器存储了一次变量a的拷贝,所以当我们第二次打印的时候就会出现随机值。
通过上述描述我们总结一下:出了函数的作用域,返回对象就销毁了,不能引用返回,否则结果是不确定的
在这里插入图片描述

函数的调用可以作为左值

然而当我们调用 test02() 后,我们输出两次后的结果相同,这是因为 test02() 中的变量a被static所修饰为静态变量,存放在全局区,而全局区上的数据在程序结束后系统释放。当我们的函数返回值为应用时,它可以类似于变量一样被重新赋值,在这里我们说函数的调用可以作为左值
在这里插入图片描述

常引用

什么是常引用呢?
我们来看一段代码:
在这里插入图片描述
当我们用const修饰变量 a 时,此时a 为常变量不可被引用。此时我们的变量a的权限是小于int& b 的权限的,权限不可以被放大,所以这里会报错,那如何修该避免报错呢?我们就使两者的权限相等就行。
在这里插入图片描述

那么我们想一下,刚刚我们说到权限不能放大那么权限能不能缩小呢?
在这里插入图片描述
我们看到这里没有报错,那么权限是可以缩小的

现在我们来看看引用和指针的不同点:
1.引用概念上定义一个变量的别名,指针存储一个变量地址
2.引用在定义时必须初始化,指针没有要求。
3.引用在初始化一个实体后,就不能在引用其他实体,而指针可以在任何时候指向一个同类型实体
4.没有NULL引用,但有NULL指针
5.在sizeof中含义不同: 引用结果为引用类型的大小,但指针始终是地址空间所占字节个数。
6.引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小。
7.有多级指针,但是没有多级引用
8.访问实体方式不同,指针需要显式解引用,引用编译器自己处理。
9.引用比指针使用起来相对更安全

内联函数

内联函数的概念

inline修饰的函数叫内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调用建立栈帧的开销,内联函数提升程序运行的效率。
在C语言中我们认识到了宏的概念

//宏
#define ADD(x,y) return ((x) + (y))
//宏的缺点
// 1.容易出错,语法细节多
// 2.不能调试
// 3.没有类型安全的检查
//

int main()
{
	//宏替换
	int a = ADD(2, 4)*5;  

	return 0;
}

宏的缺点:
1.容易出错,语法细节多
2.不能调试
3.没有类型安全的检查
宏的优点:
不用建立栈帧,提高效率

然而宏的缺点较多,在C++中我们会用 enum const inline 来代替宏

enum const ——>替代宏常量
inline ——> 替代宏函数

在这里我们用关键字inline实现内联函数

内联函数的优点:

  1. 可以调试
  2. 效率高,会展开
  3. 语法简单
inline int Add(int x, int y)
{
	int c = x + y;
	return c;
}

int main()
{
	int ret = Add(1, 2);

	cout << ret << endl;
	return 0;
}

通过反汇编窗口我们可以看到
在这里插入图片描述

那么我们上面说了内联函数的优点,那所有的函数都可以写成内联函数吗?
并不是的我们会把一些小的函数(代码十行左右)写成内联函数。

inline 不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到

//F.h
#include<iostream>
using namespace std;

inline void f(int i);

//F.cpp
#include"F.h"
void f(int i)
{
	cout << i << endl;
}

//main.cpp
#include"F.h"

int main()
{
	f(10);
	return 0;
}

上述代码会产生如下的报错
在这里插入图片描述
所以我们不要将内联函数与定义分离。

以上就是C++中引用和内联函数的相关知识。

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值