C++引用和指针
Bright-SKY 人气:0引用概念
引用的本质:给已有的变量名 取个别名
//给num取个别名为b int num =100; //&不是取b的地址 只是描述b是num的别名 编译器不会为b开辟新的空间 int &b = num;//num的别名 是b //操作b等价操作num
定义步骤
1、&修饰别名
2、给哪个变量取别名 就定义哪个变量
3、从上往下 整体替换
案例1:给数组取别名
int arr[5] ={1,2,3,4,5}; int (&new_arr)[5] = arr;
法一:
void test02() { int arr[5] = {10,20,30,40,50}; //需求:给arr起个别名 int (&my_arr)[5] = arr;//my_arr就是数组arr的别名 int i=0; for(i=0;i<5;i++) { cout<<my_arr[i]<<" "; } cout<<endl; }
法二:配合typedef
void test03() { int arr[5] = {10,20,30,40,50}; //1、用typedef 给数组类型 取个别名 //TYPE_ARR就是一个数组类型(有5个元素 每个元素位int) typedef int TYPE_ARR[5]; //myArr就是数组arr的别名 TYPE_ARR &myArr=arr; int i=0; for(i=0;i<5;i++) { cout<<myArr[i]<<" "; } cout<<endl; }
引用必须初始化
int &b;//非法的
int num = 10; int &a = num; int data = 20; a = data;//不是data别名为a 而是将data值赋值a(num)
引用初始化后不能更改
引用一旦确定是谁的别名 就不能更改
int num = 10; int &b = num; int data = 20; b=data;//千万不要认为是b给data取别名 仅仅是将data的值赋值b也就是data赋值num
引用作为函数的参数可以替代指针变量
void swap_int01(int a1, int b1) { int tmp = a1; a1 = b1; b1 = tmp; } void swap_int02(int *a1, int *b1)//a1=&a, b1=&b { //*a1 == a, *b1 == b int tmp = *a1; *a1 = *b1; *b1 = tmp; } void swap_int03(int &a1, int &b1)//int &a1 = a, int &b1=b { //a1 == a, b1 == b int tmp = a1; a1 = b1; b1 = tmp; } void test07() { int a = 10; int b = 20; cout<<"a = "<<a<<", b = "<<b<<endl; // swap_int01(a, b);//交换 不成功 // swap_int02(&a, &b);//交换 成功 swap_int03(a, b);//交换 成功 cout<<"a = "<<a<<", b = "<<b<<endl; } int main(int argc, char *argv[]) { test07(); return 0; }
引用作为函数的参数的好处:
1、函数内部 直接通过引用操作外部变量的值
2、省去了指针的操作
3、函数的形参不会拥有新的空间(节约了空间)
常引用
int &a = 10;//err
void test08() { //a就叫常引用 不能通过a修改空间的值 const int &a = 10;//ok cout<<"a = "<<a<<endl;//10 }
常引用 一般作为函数的参数 防止函数内部修改外部空间值
//常引用 作为函数的参数 即节约了空间 又防止函数内部修改外部变量的值 void printf_num(const int &a) { //a = 1000;//err cout<<" num = "<<a<<endl; } void test09() { int num = 10; printf_num(num); }
常量的引用:
void test09() { //给常量10取个别名 叫num //int &针对的是int ,10是const int类型 //const int 针对的是const int, 10是const int类型 const int &num = 10; cout<<"num = "<<num<<endl;//10 }
引用作为函数的返回值类型
当函数返回值作为左值 那么函数的返回值类型必须是引用。
(1)、通过函数返回值 在外界操作 函数内部申请的空间
int& get_data(void) { static int data = 100; //不要返回 普通局部变量的 引用 return data;//返回谁 外界的a就给data取别名 } void test10() { int &a = get_data(); cout<<"data = "<<a<<endl; }
(2)、引用作为函数的返回值类型 可以完成链式操作
引用的本质
引用的本质在c++内部实现是一个指针常量. Type& ref = val; // Type* const ref = &val;
c++编译器在编译过程中使用常指针作为引用的内部实现,因此引用所占用的空间大小与指针相同,只是这个过程是编译器内部实现,用户不可见
引用的本质:常量指针变量
int num = 10; int &b = num;//b == num //底层实现 //b是只读 *b可读可写 int * const b = # //b = 100; *b = 100;
指针的引用(了解)
new_p就是指针的引用
指针的引用的场景:
void get_memory01(int **p1)//int **p1 = &p { //*p1 == p *p1 = (int *)calloc(1, sizeof(int)); **p1 = 100; } void get_memory02(int* &p1)//int* &p1 = p { //p1 == p p1 = (int *)calloc(1, sizeof(int)); *p1 = 100;//*p1 = *p } void test13() { int *p = NULL; //get_memory01(&p); get_memory02(p); cout<<"*p = "<<*p<<endl; }
指针和引用的区别
1、引用必须被初始化(初始值必须是一个对象),指针不必(但最好要初始化)。
2、引用初始化以后不能被改变,指针可以改变所指的对象。
3、不存在指向空值的引用,但是存在指向空值的指针。
4、指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作。引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。
5、指针是一个对象,可以定义指向指针的指针。但引用不是对象,没有实际地址,所以不能定义指向引用的指针,也不能定义指向引用的引用。
加载全部内容