目录
1.引用
1.什么是引用
通俗来说就是给一个变量取别名,类似于给李明同学取一个别名叫小李一样,那么编译器不会为这个引用的变量开辟新的空间,因为两者指向的是同一块空间。
void test1() {
int a = 10;
int& b = a;
cout << a << endl;
cout << b << endl;
a++;
cout << a << endl;
cout << b << endl;
}
由此我们可以看出两者必然是指向的同一块空间,那么我们的引用也就展现了如下特性:
2.引用的特性
1.引用必须要初始化
2.一个变量可以拥有多种引用(就是可以起多个外号)
3.一个引用一旦指向了一块空间,它就不能指向另一块空间
1.常引用
我们知道变量存在常变量,那么那么对于const类型存在什么情况呢?
首先我们要明白一点,const是一个常量修饰关键字,关乎于该变量的权限问题,从int到const int是一种权限缩小 ,在应用中我们也要明白,权限只能缩小和平移,不能放大
void test2() {
const int a = 10;
//int& b = a;//权限被放大了所以会报错
const int& b = a;//权限平移
//int &c=10;//右边是常量所以也是一种权限放大,所以是错的
const int&c=10;//正确
}
3.引用使用场景
1.做参数
可以使用引用传参,在后面学习拷贝构造函数时引用也起到了关键作用,引用传参减少了对于函数调用中值拷贝形参无法改变实参的问题:
void test2(int& a1, int& b1) {
a1++;
b1++;
}
nt main() {
int a = 5;
int b = 6;
test2(a,b);
cout << a << endl;
cout << b << endl;
return 0;
}
2.可以做返回值
返回值存在两种方式:
1.传值返回
把要返回的n(出了作用域n会被销毁)的值传给一个临时变量(由寄存器实现,开辟函数栈帧)然后把这个值接受
2.传引用返回
返回n的别名,那么就需要n,即使它销毁了但是它的空间必须还在(就像是用名字去申请了一个图书馆座位,人走了但是图书馆座位还在),由别名所指向,否则就会出现问题,总的来说想要传引用返回就是这几种情况:
1.返回对象还在
2.需要对返回对象进行修改操作
3.像顺序表一样进行访问(在后面学习运算符重载时会用到)
之所以使用传引用的方式,也是因为传值存在值拷贝问题,是传递实参变量的一份临时拷贝,那么当参数非常大时就会让效率很低
4.引用和指针的区别
首先引用它只是一个别名,所以它并没有独立的空间,和实体共用一块空间,从底层来看引用本质还是通过指针去实现的
1.引用定义一个变量的别名,指针存储一个变量的地址
2.引用在定义时必须初始化,指针并没有要求
3.引用在初始化引用一个实体后不能再指向其他实体,但是指针可以随便修改指向的空间
4.不存在空引用但是存在空指针
6.给引用++是给引用的实体++,而指针++是指针向后偏移一个类型的大小
7.sizeof中引用的大小为实体的大小,而指针始终是4或8个字节
8,再访问实体上指针需要解引用,而引用由编译器自己操作
2.内联函数(incline修饰的函数)
1.概念
我们曾经学过宏的概念,分为宏常量和宏函数:
#define MAX 100
#define ADD(x,y) ((x)+(y))//没有参数类型会完全替换
//括号用于保证优先级
会存在以下问题:
1.不能调试
2.无安全类型检查
3.由于存在优先级问题极其容易写错
但是它由于没有类型严格限制以及不需要建立函数栈帧提高了效率也有优点, 那么内敛函数就是宏函数基础上的一个升级
incline修饰的函数叫做内联函数,咋编译时会再调用内联函数的地方展开,没有函数调用建立栈帧提升效率
2.内联函数特点
1.incline是 一种以空间换时间的做法,在编译阶段会用函数体替换函数调用
2.incline对于编译器而言只是建议,如果函数存在递归以及频繁调用那么编译器会忽略
3.incline不建议声明和定义分离,会导致链接错误,因为incline被展开没有函数地址,链接就会找不到
3.auto关键字
常运用于:1.类型太长难于拼写
2.含义不明确容易出错(在后面学到string时就会体会到)
auto定义必须对其进行初始化,在编译阶段要根据初始化表达式推到auto的实际类型,它并非时一种类型声明,而是类型声明时的占位符,在编译时期会将其替换
auto不能推导的类型:
1.不能作为函数参数
2.不能直接用于声明数组
4.范围for循环
对于一个有范围的集合,循环范围还要再写一遍看起来是多余的并且容易写错所以引入了范围for,它可以自动判断结束,自动迭代
1.范围for构成
1.由冒号分为两部分前者为用于迭代的变量
2.后半部分为用于被迭代的范围
int arr[] = { 1,2,3,4,5 };
for (auto i : arr) {
cout << i << " "; // 1 2 3 4 5
}
2.范围for使用条件
1.迭代范围必须确定
对于数组就是第一个元素到最后一个元素的范围,对于类利用begin和end来控制范围
int arr[5] = { 1,2,3,4,5 };
for (int i : arr) {
cout << arr[i] << " ";//由于for范围不确定造成随机数的打印
}
2.迭代对象要实现++和==操作
(还会继续更新,欢迎各位大佬批评指正)