引用相关知识介绍
1、引用的概念与特性`
#include "SeqList.h"
int main()
{
// 1、引用的概念(给已存在的变量取别名)
int a = 0;
int& b = a; //给变量a取别名为:b
cout<< &a <<endl; //取a地址
cout<< &b <<endl; //取b地址
a++;
b++;
// 2、引用的特性
int a = 1;
int& b = a; //A\ 引用在定义时必须初始化。
int& b = a; //B\ 一个变量可以有多个引用(别名)
int& c = a;
int& d = c;
a++;
int x = 10;
b = x; //这里是将x赋值给b
// C\ 引用一旦引用一个实体,再不能引用其他实体。
return 0;
}
2、引用的用途
2.1 做输出型参数
// (1)做输出型参数
//例1 Swap交换
void Swap(int& r1,int& r2)
{
int tmp = r1;
r1 = r2;
r2 = tmp;
}
int main()
{
int a = 0;
int b = 2;
Swap(a,b);
return 0;
}
//例2 顺序表
typedef struct SeqList
{
//.....
}SL;
void SLPushBack(SL& s,int x) //SL& s=sl; 这里的s是sl的别名,这里的形参是实参的别名,进而导致形参改变,影响到了实参。
{
//.....
}
int main()
{
SL sl;
SLPushBack(sl,1);
SLPushBack(sl, 2);
SLPushBack(sl, 3);
return 0;
}
//例3、单链表
typedef struct SListNode
{
//.......
}SLTNode,*PSLTNode; //*PSLTNode的意思为:typedef SLTNode* PSLTNode;
//void SListPushBack(SLTNode** pphead, int x) //这里用二级指针接收
//void SListPushBack(SLTNode*& phead, int x) //这里用指针变量的引用(别名)接收
void SListPushBack(PSLTNode& phead, int x) //PSLTNode 相当于 SLTNode*
{
//......
}
int main()
{
SLTNode* list;
//SListPushBack(&list,1);
//SListPushBack(list, 2);
SListPushBack(list, 3);
return 0;
}
2.2 做输出型返回值
2.2.1 做输出型返回值的条件
应用条件:如果出了函数的作用域,返回对象就销毁了,那么一定不能用引用返回,一定要用传值返回。
//(1)传引用返回(返回的是:返回对象的别名)
int& Count()
{
int n = 0; //(有static时,出了函数Count的作用域,n在静态区内且未销毁,可以用传引用返回)
n++; //(没有static时,n在栈区内,出了函数Count的作用域,n就销毁了,无法用传引用返回)
return n; //这里返回的是:返回对象n的别名(假设为tmp; int& tmp=n;)
}
int main()
{ // int ret=tmp;[tmp是n这块空间的别名]
int ret = Count(); //ret的结果是随机的。如果栈帧结束,系统会销毁栈帧置成随机值,那么这里ret的结果就是随机值。
cout << ret << endl;
cout << ret << endl;
return 0;
}
//(2)额外补充:传值返回(返回的是:返回对象值的临时拷贝)
int Count()
{
int n = 0;//(没有static时,n在栈区内)(有static时,n在静态区内)
n++;
return n;
}
int main()
{
int ret = Count();
cout<< ret <<endl;
return 0;
}
2.2.2 具体应用
Test.cpp
#include "SeqList.h"
int main()
{
SL sl;
SLInit(sl);
SLPushBack(sl,1);
SLPushBack(sl, 2);
SLPushBack(sl, 3);
SLPushBack(sl, 4);
for (int i=0;i<sl.size;i++)
{
cout<< SLAt(sl,i) <<" ";
}
cout << endl;
//引用做返回值,既可以直接打印,也可以直接修改
//SLAt(sl,i)的返回值是返回对象s.a[pos]的别名;出了函数SLAt的作用域,s.a[pos]只是名字没了,实际数组没有销毁,因为数组是开辟在堆区上的。
SLAt(sl,0)++;
SLAt(sl,2) = 10;
for (int i = 0; i < sl.size; i++)
{
cout << SLAt(sl, i) << " ";
}
cout << endl;
return 0;
}
SeqList.h
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
using namespace std;
typedef struct SeqList
{
int* a;
int size;
int capacity;
}SL;
void SLInit(SL& s, int capacity = 4);
void SLPushBack(SL& s, int x);
//修改顺序表数据的函数
//void SLModify(SL& s,int pos,int x);
int& SLAt(SL& s,int pos);
SeqList.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"
void SLInit(SL& s, int capacity)
{
s.a = (int*)malloc(sizeof(int)*capacity);
assert(s.a);
s.size = 0;
s.capacity = capacity;
}
void SLPushBack(SL& s, int x)
{
if (s.size==s.capacity)
{
//......
}
s.a[s.size] = x;
s.size++;
}
int& SLAt(SL& s, int pos)
{
assert(pos>=0 && pos<s.size);
return s.a[pos];
}
2.3 做输出型参数或输出型返回值时,均能提高效率
3、const引用
3.1 const引用权限
int main()
{
//4.1 const引用权限
//引用权限平移
int a = 2;
int& b = a;
cout<< typeid(a).name() <<endl;
cout << typeid(b).name() << endl;
//引用权限放大(不行)
const int c = 1;
//int& d = c;
const int& d = c;
//引用权限缩小
int e = 4;
const int& f = e;
//权限的平移例子:
int ii = 2;
//double& rdd = ii;
const double& rdd = ii;
// 中间产生一个 const double类型的临时变量:tmp
const int& x = 10;
return 0;
}
3.2 const引用的应用
void func(const int& n) //如果使用 引用传参,且函数内不改变n,则建议尽量用const引用传参。(因为const引用传参的接受度很高)
{
}
int main()
{
int a = 2;
const int b = 3;
func(a);
func(b);
func(10);
return 0;
}
文章介绍了C++中的引用概念,作为已存在变量的别名,必须在定义时初始化。引用用于做输出型参数和返回值,可以提高效率。const引用用于只读访问,提高了代码的可读性和安全性。文章通过示例代码展示了引用在函数参数和返回值中的应用,并强调了const引用的权限和使用场景。

被折叠的 条评论
为什么被折叠?



