- 何为引用
- 引用的形式
- 引用的作用
- 引用与指针
引入:
我们在生活中可能会有多多少少的外号(小名),而这个外号即是别名,在语法的层面上c++中的引用就是别名
引用的讲解
这句话很重要!!!!
***对引用的操作直接反应到所引用的实体(变量或对象)***
1.引用变量
void quoteTest_1() {
int a = 10;
// b为a的引用,为引用变量
int& b = a;
// 这里体现一个对象可以有多个别名
int& c = a;
int& d = a;
cout << "这里体现a和a的引用变量b共用一块地址" << endl;
cout << &a << endl << &b << endl;
}
另外 对于quoteTest_1()的补充
2.作为函数的传入参数
// c语言中形参应当为指针变量
void swap(int& left, int& right) {
// 直接通过引用变量操作
int tmp = left;
left = right;
right = tmp;
}
void quoteTest_2() {
int x = 10;
int y = 2;
// 传入的x代表引用变量left同
swap(x, y);
}
// 这里我们在c语言中,对一个数通过函数进行操作需要找到它的地址然后操作,因为函数传入的形参一般是一份临时的拷贝,因为引用相当于变量的别名,我们传入的变量通过引用的改变直接完成了变量的改变,就是通过引用这个桥梁直接连接了函数和实参
struct ListNode {
struct ListNode* next;
int value;
};
// 链表尾插
// 这里通过引用变量phead存放一个指针变量,替代了二级指针的使用
void pushBackList(struct ListNode*& phead, int x) {
struct ListNode* newNode = (struct ListNode*)malloc(sizeof(struct ListNode));
newNode->value = x;
newNode->next = NULL;
if (phead == NULL) {
// 省下了解引用这一步
phead = newNode;
}
else {
struct ListNode* current = phead;
while (current->next != NULL) {
current = current->next;
}
current->next = newNode;
free(current);
}
}
void quoteTest_3() {
// 直接通过变量进入引用变量
struct ListNode* plist = nullptr;
// 通过外号等同进入
pushBackList(plist, 1);
pushBackList(plist, 2);
}
3.引用作为函数返回值
// 引用作为函数返回值函数
int& count() {
// 注意这里的n为临时变量,在调用结束后栈帧销毁,n的占有空间可能销毁
int n = 0;
n++;
return n;
}
void quoteTest_4() {
// 因为count调用后就可能把开辟的空间给回收,相当于return n可能被指为随机值
int ret = count();
cout << "这里ret可能为1或者随机值" << endl;
cout << ret << endl;
cout << ret << endl;
// 这里可以直接对引用函数赋值
count() = 4;
cout << count() << endl;
}
另外我们通过直接修改引用函数的值发现会受到函数内的变量生存周期销毁而产生随机值的影响,那么如果我们对数组,链表这一类不受当前函数生存周期影响作用时,会发生什么呢?
那么以顺序表为例子
// 对顺序表修改值的接口的改良
struct seqList {
int *array[19];
int size;
int capacity;
// 引用也可以作为结构体内放一个成员函数
int& seqListFind(int i) {
return *array[i];
}
};
// 传一个别名进来,实际上就是不需要进行形参的临时拷贝,直接对操作对象进行操作
int& seqListChange(struct seqList& pList, int i) {
// 第i个位置小于总大小
assert(i < pList.size);
// 因为引用作为返回值的时候相当于int的别名,就需要返回一个int,那么对指针数组解引用
return *pList.array[i];
}
void quoteTest_5() {
struct seqList list;
list.size = 20;
// 因为是一个引用函数所以可以找到拿一块空间对应的值进行修改
seqListChange(list, 2) = 10;
seqListChange(list, 1) = 6;
}
4.引用与指针
引用表面上是传值,底层是有指针来实现的,所以本质上引用也是传地址,区分如上图