C++ 引用&(左值引用)

目录

1、引用的定义

2、引用的特点

3、引用作为形参代替指针

4、const与引用

4.1、const int& 

4.2、int& const

5、其他使用方式

5.1、&与数组

5.2、&与指针

6、引用与指针的差别

7、不可以对函数中的局部变量或对象以引用、指针的方式返回

8、&实质: int &p = a; <=> int *const p = a;

9、分析效率 函数形参:变量、指针、引用


1、引用的定义

        引用的定义类型&  引用变量名称 = 变量名称;

        这就是引用变量的定义。&类型结合称之为引用符号,不是取地址符,代表引用的意思。

int main()
{
    int a = 0;
    int b = a;//变量
    int &c = a;//引用

    return 0;
}

        此时,c 就是 a 的别名,c等价于a:c就是a,a就是c ,就像鲁迅就是周树人,周树人就是鲁迅。

        此时,若将c的值改为10,也就是将a的值改为了10。

        引用的大小,也就是其所指变量的大小:

2、引用的特点

        引用有如下特点:

1、引用必须初始化。

2、没有空引用。

3、没有引用的引用(二级引用、多级引用)。

4、一个引用一旦被初始化为一个变量的别名,就不能更改、再成为其他变量的引用(别名)。

          若存在二级引用 "int&& n = m;",由于 m 与 a 等价,则存在 "int&& n = a;",这显然是不成立的。

3、引用作为形参代替指针

        在学习引用之前,在C语言基础上,假设我们要编写一个两值交换函数 swap(a,b) ,由于需要实现对形参a、b所传入的值进行交换,继而影响实参的两值进行交换,所以,我们需要将实参两变量的地址(指针)传入函数,进行解引用交换。

void swap(int* a,int* b){
    //对于一切传入函数的指针,先进行安全性检查
    assert(a!=nullptr&&b!=nullptr);
    int tmp=*a;
    *a=*b;
    *b=tmp;
}

         因为引用是原变量的别名,等价于原变量,如果我们将形参换位两变量的别名,也可以实现在函数中两值交换,影响原变量值交换。

void swap(int& p,int& q){
    int tmp=p;
    p=q;
    q=tmp;
}

         此时的代码更简洁,而且因为形参是引用,不需要进行判空(没有空引用)。 

4、const与引用

4.1、const int& 

        const 在修饰引用时,只有一个作用,就是限制该引用(别名)只能读,不能写(修改)

        若一个变量被 const 修饰为常变量,则其引用也必须被const修饰为常引用

         添加const后正确。

        " const int& 引用变量名称 " 也被称为万能引用,可以成为任何相同类型变量的引用。但也就不能通过引用改变其对应变量的值

         " const int& u = 100; " 的实质为 系统开辟临时变量tmp用于保存100,u再成为变量tmp的别名

4.2、int& const

        若 const 在 & 后面(右边)(int& const p = a;),则与const在修饰指针时一般,此时const修饰引用p不能再成为别人的引用,但引用本身就有只能绑定一个变量的特点,所以 & 右边的 const 是无效的,编译时被忽略

5、其他使用方式

5.1、&与数组

        若此时定义有数组arr{ 1,2,3,4,5 },我们可以通过 "int& p = arr[i];" 的方式,为数组单个元素添加引用。

        此时,p是arr[0]的引用,p的地址就是arr[0]的地址

        若要为整个数组添加引用,不能直接使用 "int& q = arr;" 的方式,此时arr代表整个数组,是 int[5] 类型的,我们也要以 int(&)[5] 类型为 arr 添加引用

         此时,q就等价于arr,q与arr地址相同,可以通过 q[i] 来访问数组arr第 i 个值(0=<i<5)。

        sizeof(q) 的大小等于 sizeof(arr) 的大小,也就是数组的大小。

5.2、&与指针

int main()
{
    int a = 10, b = 20;
	int* p = &a;//指针p指向a
	int*& rp = p;//rp为指针p的引用
    //rp等价于p
	rp = &b;//修改rp的指向为b

    return 0;
}

        如图,a的值为10,a的地址为 0x0096f7d4,此时,指针p与引用指针rp的值都为变量a的地址解引用后都是a的值10p与rp的地址也相同

        在执行" rp = &b; "后,p的指向被修改为变量b,值为b的地址,解引用后为b的值20。

6、引用与指针的差别

指针引用
1从语法规则上讲,指针变量存储某个实例(变量或对象)的地址;引用是某个实例的别名。
2程序为指针变量分配内存区域;而不为引用分配内存区域,别名的内存地址是其所指实例的地址。
3指针在访问其所指变量时需要解引用;引用可以直接使用。
4指针变量的值可以改变,存储不同实例的地址(修改指向);一个引用在定义时就被初始化,绑定为一个实例的引用,无法在成为其他实例的引用。
5指针变量的值可为空(NULL,nullptr);没有空引用。
6指针变量在作为形参时需要测试它的合法性(判空);引用不需要判空。
7对指针变量使用"sizeof"得到的是指针变量的大小;对引用使用"sizeof"得到的是其对应变量的大小。
8理论上指针的级数没有限制;引用只有一级,不存在引用的引用。
9++指针会使指针变量指向下一个实例的地址,而不是修改所指实例的内容;++引用会直接影响到引用对应的实例。

7、不可以对函数中的局部变量或对象以引用、指针的方式返回

int add(int a,int b){
    int c = a + b;
    return c;
}

         这是一个简单的求和函数,在main函数中执行到这个函数时,系统会为这个函数开辟栈帧,供add函数去执行;执行完成后,用一个临时变量保存返回的数据值,然后回收为add开辟的栈帧。

int* funa() {//error
	int a = 10;
	return &a;
}
int& funb() {//error
	int a = 10;
	return a;
}

         假如这两个函数在程序中运行。通过上面的学习可以知道,引用的地址是其对应变量的地址,而指针也保存的其指向变量的地址。

        上面funa函数返回的指针是funa函数运行时产生的局部变量的地址。在函数运行结束后,栈帧被回收,这段栈帧就不能被随意访问了,但此时通过函数的返回值,我们还拥有这段栈帧中的一个地址,就可以解引用访问,但这是非法的,所以funa是错误的。

        funb函数返回的是其栈帧中变量a的别名,所以这个别名也就是funb栈帧内存中的局部变量。在funb运行结束后,栈帧被回收,其中全部局部变量死亡,但我们可以通过返回值去访问原funb栈帧中内存地址的变量,这也就是非法的。

8、&实质: int &p = a; <=> int *const p = a;

        在语法上,引用本质上是一个指向其对应变量的指针常量int &p = a; <=> int *const p = a;。在使用时,我们只需像使用普通变量般使用它,无需解引用等操作,系统在编译运行时,自动将使用引用的地方进行了如下替换。

        所以,在编译阶段,指向一个变量的指针和其引用初始化的代码才会一模一样。

        所以,引用原本就被const修饰为常变量,这也是一个引用只能绑定一个实例的原因。

9、分析效率 函数形参:变量、指针、引用

struct Student {
	char s_id[20];
	char s_name[20];
	char s_sec[10];
	int s_age;
};

void funa(struct Student s1) {}//值传递
void funp(struct Student* sp){} //指针传递
void funb(struct Student& s2) {}//引用//底层是指针

        对于值传递,只在实参初始化形参时,访问实参一次内存;对应指针传递,在使用实参地址初始化形参时,访问实参一次内存,再至少在使用一次实参的值时访问一次实参地址,总共至少访问两次实参地址;对于引用做实参,在实参初始化引用形参时,访问实参一次内存,也再至少在使用一次实参的值时访问一次实参地址,总共至少访问两次实参地址

        所以,在参数字节大小较小,且无需通过形参改变,影响实参的值时,尽量使用值传递的方式,效率高在参数较大,或需通过形参改变,影响实参的值时,使用指针与引用效率相当,但引用使用更简单

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值