目录
1.引用的介绍
在C++中提供了一种不使用指针变量同样可以达到同样效果的机制,并且使用起来更方便,这种机制叫做"引用"。
2.引用和指针的区别
引用和指针可以实现相同的功能,但是实际上两者有很大区别:
| 特性 | 指针 | 引用 |
|---|---|---|
| 定义与初始化 | 存储变量的地址,可以不初始化或初始化为nullptr | 必须初始化,且一旦绑定后不可更改绑定的变量 |
| 内存地址 | 有自身的内存地址,存储另一个变量的地址 | 没有独立的地址,与被引用的变量共享地址 |
| 重新赋值 | 可以重新指向其他变量或设置为nullptr | 不可重新绑定到其他变量 |
| 空值 | 可以为null | 必须绑定到有效对象,不能为null |
| 操作符 | 使用*解引用,->访问成员 | 直接使用,无需特殊操作符 |
上面比较重要的是内存地址。引用可以理解为给变量名起了一个别名,就好比一个人有大名,有小名,也会有代号,指向的都是一个人。而指针则是开辟了一个新的空间,这个空间里存放原有变量的地址,通过这个地址来对原变量进行操作。不理解没没关系,直接看代码。
3.引用的简单使用
#include <iostream>
int main(void)
{
//引用部分
int age = 10;
//这里的'&'不是地址符,而是对age进行引用
int "e = age;
quote = 23;
//打印信息
std::cout << "age : "<< age << std::endl;
std::cout << "quote : "<< quote << std::endl;
std::cout << &age << std::endl;
std::cout << "e << std::endl;
//指针部分/
int num = 20;
int *p = #
*p = 32;
//打印信息
std::cout << "num : "<<num << std::endl;
std::cout << "*p : "<< *p << std::endl;
std::cout << &num << std::endl;
std::cout << p << std::endl;
std::cout << &p << std::endl;
}
结果如图:

上述的代码中,分别使用了引用和指针对一个变量进行间接的赋值,从打印的结果来看,quote和age的值相同,说明quote和age指向的是同一块地址,quote的值改变,则age的值也发生了改变,并且从打印的地址来看,二者确实是指向同一块地址,这就是引用。
至于指针,相信大家也都了如指掌了,这里也没什么不一样,主要用来对比,不多解释。
4.对数组和指针的引用
在引用的时候,引用的类型必须和绑定变量的类型一致,有点熟悉是吧,没错,引用和指针的规则是一样的,来看这段代码:
#include <iostream>
int main(void)
{
int data = 10;
int* p = &data;
int* "e = p;
//这里实际上是给指针p起了一个别名quote,
//所以这里就可以像使用p一样来使用quote。
//例如通过*quote = 20;来改变data的值。
std::cout << "&p : "<<&p << std::endl;
std::cout << ""e : " << "e << std::endl;
return 0;
}
结果如图:

从结果来看这&p和"e指向的是同一块地址,这是引用的特征,没有问题,但需要注意的是int* "e = p;这一行代码,这里定义引用的类型一定要和变量的类型一致,p是什么类型的?是int*类型,还不会判断变量类型的可以看一下我之前C指针那篇文章。
那么对指针的会了,对于数组的引用自然也就轻车熟路了,简单示例:
int buf[32] = {0};
int ("e)[32] = buf;
std::cout << "buf : " << buf << std::endl;
std::cout << "quote : " << quote << std::endl;
结果如图:
5.引用作为参数
引用作为参数是比较常见的操作,具体的写法如下:
#include <iostream>
void change_value(int &num)
{
num = 425;
std::cout << "num的地址" << &num <<std::endl;
}
int main(void)
{
int data = 100;
std::cout << "data的地址" << &data <<std::endl;
change_value(data);
std::cout << "data : " << data << std::endl;
return 0;
}
结果如下:
只需要在参数的添加上&就可以了,那么传入的就应该是一个引用,相较于指针,可以不用再去创建的一个临时的形参,节省了资源。
6.引用作为返回值
引用作为返回值,有一点需要注意(重点),就是不能返回一个局部变量的引用,在函数执行结束后,局部变量会被销毁,那么这时引用就出错,导致悬空引用和未定义行为出现。所以一定不要返回一个函数中的局部变量的引用。总之就是要避免引用的变量出现悬空,一般引用全局变量和静态变量。关于引用的写法如下:
#include <iostream>
#include <string>
// 全局变量定义
std::string str = "hello world";
int num = 20;
int &count = num;
int &fun(int a,int b)
{
count = a+b;
return count;
//引用实际上是给一个变量起了一个别名,所以返回num和count是没有区别
}
// 函数返回全局变量的引用
std::string &function() {
str = "hello";
return str;
//错误写法,不能返回局部变量的引用
//std::string new = "apple";
//std::string "e = new;
//return qupte;
}
int main() {
std::cout << "str : " << str << std::endl; // 输出: hello world
std::string &ref = function();
std::cout << "ref : " << ref << std::endl;
std::cout << "num : " << num << std::endl;
count = fun(3,4);
std::cout << "num : " << num << std::endl;
std::cout << "count : " << count << std::endl;
return 0;
}
结果如图:

7.常引用
常引用就是在引用的时候前面加上const关键词,使用了引用,就不允许通过该引用对其所绑定的变量或对象进行修改。
这些就是引用的所有使用了,使用起来一定要记得使用规则。

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



