引用
- 引用的概念
- 引用的定义
- 引用的使用
- 引用的应用
- 引用的本质(就是C++内部的一个常指针(type * const 名))
- 指针引用(其类型还是指针type *)
- 常引用(采用const修饰的引用)
引用的概念
1、通常我们说的引用指的是“左值引用”,顾名思义就存在右值引用咯,先不展开。
2、引用就是为已经存在的变量起别名,必须是已经声明存在的变量才可以
3、引用也是C++中的一种复合类型
4、引用只是C++的特性,C中是不存在的
引用并不是对象,它只是为已经存在的对象起了一个别名而已
引用的定义
假设有变量
int b = 100
;
int &a = b
;//a指向b,即a是b的另一个名字
但是下面的使用是不对的:
int &a
;
引用必须要被初始化
那申明引用为何一定要初始化呢?
因为引用只是已存在变量的别名,我们在初始化变量的时候是将初始值拷贝到新建的对象中,然而在声明引用的时候,需要将引用和它的初始值对象一直绑定,因为引用是不可能绑定到另一个对象上的,因此必须初始化。
并且引用的定义是可以在一条语句中定义多个引用的,其中每个引用都是以&
开头,如下:
int a = 100,b = 200;
int c = 100,d = 200;
int &r = a,c = b;
int &e = c,&f = d;
那么给定义引用之后获取到的值、地址又是什么样的?
引用的使用
由下图可知:
1、为引用赋值,就是将值赋给与引用绑定的对象
2、引用与其绑定的对象的值和地址都是相同的
引用的应用
普通引用在声明时必须用其它的变量进行初始化
引用作为函数参数声明时不进行初始化
以交换两个数x/y的值为题来看,代码如下:
#include <stdio.h>
#include <stdlib.h>
//众所周知这种方式不能交换两个数的数值
void swap(int a, int b)
{
int tmp = a;
a = b;
b = tmp;
}
//方式一, 使用指针完全可以
void swap1(int *a, int *b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
//方式二, 使用引用完全可以
void swap2(int &a, int &b)
{
int tmp = a;
a = b;
b = tmp;
}
int main(void){
int x = 10, y = 100;
//swap1(&x, &y);//x = 100,y = 10
swap2(x, y);//x = 100,y = 10
printf("x: %d, y: %d\n", x, y);
system("pause");
return 0;
}
引用之所以能体现出指针的效果,是因为修改引用的值就是修改与其绑定对象的值。
引用的本质(就是C++内部的一个常指针(type * const 名))
对于同一块内存空间而言可以取好多个名字(即对同一个变量可以取多个别名),而且引用还有自己的空间。综合来看指针很像常指针。
int a = 200
;
int &b = a
;
const int * c = &a
;
a是一个变量,b是该变量的别名,c是一个常指针指向a的地址。
即:Type& name<-->const Type* name
,Type是对应的数据类型
我们通过常指针改变交换两个变量数值的函数如下:
void swap1(int * const a, int * const b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
int main(void){
int x = 10, y = 100;
swap1(&x, &y);
printf("x: %d, y: %d\n", x, y);//x = 100,y = 10
system("pause");
return 0;
}
C++编译器在编译过程中使用常指针作为引用的内部实现,因此引用所占用的空间大小与指针相同。
指针引用(其类型还是指针type *)
命名规范:Type * &引用名 = 指针名
意思为:指向指针变量的引用,其还是一个指针变量(更简单的说法是:指针引用就是给指针起个别名)
简单使用如下:
p和其引用q都是指针变量
#include <stdio.h>
#include <stdlib.h>
int main(void){
int x = 666;
int *p = &x;
int * &q = p;
printf("*p: %d, *q: %d\n", *p, *q);//666,666
system("pause");
return 0;
}
它的使用有什么好处呢?当然有,跟二级指针相关,使用二级指针可以将变量带入被调函数也可以带出被调函数,以下面举例:
#include <stdio.h>
#include <stdlib.h>
void boy_home(int **meipo){
static int boy = 23;
//*meipo~ &meipo
*meipo = &boy;
}
//指针的引用
void boy_home1(int* &meipo){
static int boy = 23;
meipo = &boy;
}
int main(void){
//声明空指针
int *meipo = NULL;
//一直指针的地址就是二级指针的值
//boy_home(&meipo);
boy_home1(meipo);
//打印meipo这个一级指针上面的值
printf("boy: %d\n", *meipo);
system("pause");
return 0;
}
常引用(采用const修饰的引用)
语法:const Type& name = var;
常引用有两种声明的形式:
第一种是:用变量初始化常引用
int a = 100
;
const int &b = a
;
第二种是:用字面量初始化常量引用
const int a = 100
;
const int &b = a
;
int main(void){
int a = 10;
//int &b = a;//可以通过引用去改变与其绑定的变量对象的值
//1.用变量初始化常引用
const int &b = a;
//常引用是让变量引用变成只读,不能通过引用对变量进行修改
//b = 100;
printf("a: %d\n", a);
//2.用字面量初始化常量引用
const int c1 = 10;
//这个是在C++中,编译器会对这样的定义的引用分配内存,这算是一个特例
//const int &c2 = 10; //尽量不要这么写
const int &c2 = c1; //可以这么写
//c2 = 100;//不能修改
system("pause");
return 0;
}
常量引用不能用来修改与其绑定的变量的值,因为有const关键词修饰
const 引用结论:
1)常引用const int & e
相当于常指针const int * const e
(引用的底层就是常指针)
2)普通引用相当于int *const e1
3)当使用常量(字面量)对const引用进行初始化时,C++编译器会为常量值分配空间,
并将引用名作为这段空间的别名
4)使用字面量对const引用初始化后,将生成一个只读变量