当前位置 博文首页 > Zhi Zhao的博客:C++入门基础教程(二):const限定符 与 “引用”

    Zhi Zhao的博客:C++入门基础教程(二):const限定符 与 “引用”

    作者:[db:作者] 时间:2021-08-08 13:08

    ?????目录

    前言

    一、const限定符

    二、引用

    1 引用的定义

    2 引用做函数参数

    3 引用做函数返回值

    4 引用的本质

    5 常量引用

    结束语


    前言

    博主通过对C++基础知识的总结,有望写出深入浅出的C++基础教程专栏,并分享给大家阅读,今后的一段时间我将持续更新C++入门系列博文,想学习C++的朋友可以关注我,希望大家有所收获。

    一、const限定符

    (1)const int *p=&a 常量指针:指针指向可以修改,但是指针指向的值不可以改变。
    (2)int * const p=&a 指针常量:指针指向不可以修改,但是指针指向的值可以改变。
    (3)const int * const p=&a ?既修饰指针又修饰常量:指针指向和指针指向的值都不可以改变。

    int a = 10, b = 20;
    // 1、const修饰指针 常量指针:指针指向可以修改,但是指针指向的值不可以改变
    const int * p1 = &a;
    p1 = &b;   // 正确
    *p1 = 30;  // 错误
    
    // 2、const修饰常量 指针常量:指针指向不可以修改,但是指针指向的值可以改变
    int * const p2 = &a;
    p2 = &b;   // 错误
    *p2 = 30;  // 正确
    
    // 3、const修饰指针和常量 既修饰指针又修饰常量:指针指向和指针指向的值都不可以改变
    const int * const p3 = &a;
    p3 = &b;   // 错误
    *p3 = 30;  // 错误

    记忆方法:

    (1)按照顺序将const 翻译为常量,* 翻译为指针,就可区分常量指针和指针常量。

    (2)const 修饰指针时,*p为解引用,const 实际上限定的是指针指向的对象,指针本身并没有被限定,所以指针的指向是可以改变的,但其指向的对象相当于常量,不能改变。

    (3)const 修饰常量时,* 在const 限定符前面,const p 限定的是指针 p,此时 p 的值便不能改变,即指针 p的指向是恒定的,而指针 p 指向的对象没有被限定,这个对象的值是可以改变的。

    二、引用

    1 引用的定义

    语法:数据类型 &别名 = 原名

    作用:给变量起别名

    int a = 10;
    int &b = a;

    注意事项:(1)引用必须要初始化;(2)引用一旦初始化后,就不可以更改。

    一般在初始化变量时,初始值会被拷贝到新建的对象中。但是定义引用时,程序是将引用和它的初始值绑定在一起,而不是将初始值拷贝给引用。一旦初始化完成,引用将和它的初始值对象一直绑定在一起,不可以更改绑定的对象。

    例1
    int a = 10;
    
    // 1、引用必须初始化
    int &b; // 错误,必须要初始化
    int &b = a;
    
    // 2、引用在初始化后,不可以更改绑定的对象
    int c = 20;
    &b = c; // 错误
    b = c; // 赋值操作,而不是更改引用
    
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    cout << "c = " << c << endl;

    以上代码输出a、b、c的值都是20。

    2 引用做函数参数

    作用:函数传参时,可以利用引用的技术让形参修饰实参

    // 例2:引用传递,交换数据
    void mySwap(int &a, int &b)
    {
    	int temp = a;
    	a = b;
    	b = temp;
    }
    
    int main()
    {
    	int a = 10, b = 20;
    	mySwap(a, b);
    
    	cout << "a= " << a << endl;
    	cout << "b= " << b << endl;
    	system("pause");
    	return 0;
    }

    3 引用做函数返回值

    用法:函数的调用可以作为左值。

    注意:不要返回局部变量的引用。

    例3
    // 1、不要返回局部变量的引用
    int& test01()
    {
    	int a = 10; // 局部变量存放在四区中的栈区
    	return a;
    }
    // 2、函数的调用可以作为左值
    int& test02()
    {
    	static int a = 10; // 静态变量,存放在全局区,全局区上的数据在程序结束后系统释放
    	return a;
    }
    
    int main()
    {
    	int &ref1 = test01();
    	cout << "ref1 = " << ref1 << endl;   // 第一次结果正确,是因为编译器做了保留
    	cout << "ref1 = " << ref1 << endl;   // 第二次结果错误,因为a的内存已经释放
    	
    	int &ref2 = test02();
    	cout << "ref2= " << ref2 << endl;
    	cout << "ref2= " << ref2 << endl;
    	test02() = 1000; // 如果函数的返回值是引用,这个函数调用可以作为左值
    	cout << "ref2= " << ref2 << endl;
    	cout << "ref2= " << ref2 << endl;
    	
    	system("pause");
    	return 0;
    }

    4 引用的本质

    引用的本质在C++内部实现是一个指针常量(指针指向不可以修改,但是指针指向的值可以改变)。

    int a=10;
    int &ref=a;  // 编译器自动转换为 int * const ref=&a;
    ref=20;      // 内部发现ref是引用,自动转换为 *ref=20;

    5 常量引用

    作用:修饰形参,防止误操作。

    int &ref = 10; ?      // 错误,引用必须引一块合法的内存空间
    const int &ref = 10; ?// 加上const之后,编译器将代码修改:int temp=10;const int &ref = temp;
    ref = 20; ? ?         // 错误,加入const之后变为只读,不可以修改。

    术语:常量引用是对 const 的引用

    C++程序员们经常把词组“对 const的引用”简称为“常量引用”,这一简称还是挺靠谱的,不过前提是你得时刻记得这就是个简称而已。

    严格来说,并不存在常量引用。因为引用不是一个对象,所以我们没法让引用本身恒定不变。事实上,由于C++语言并不允许随意改变引用所绑定的对象,所以从这层意义上理解所有的引用又都算是常量。引用的对象是常量还是非常量可以决定其所能参与的操作,却无论如何都不会影响到引用和对象的绑定关系本身。

    关键概念:某些符号有多重含义

    int i = 42;
    int &r = i;    // &紧随类型名出现,因此是声明的一部分,r是一个引用
    int *p;        // *紧随类型名出现,因此是声明的一部分,P是一个指针
    p = &i;        // &出现在表达式中,是一个取地址符
    *p = i;        // *出现在表达式中,是一个解引用符
    int &r2 = *p;  // &是声明的一部分,*是一个解引用符

    ?在声明语句中,& 和 * 用于组成复合类型;在表达式中,它们的角色又转变成运算符。在不同场景下出现的虽然是同一个符号,但是由于含义截然不同,所以我们完全可以把它们当作不同的符号来看待。

    结束语

    大家的点赞和关注是博主最大的动力,博主所有博文中的代码文件都可分享给您(除了少量付费资源),如果您想要获取博文中的完整代码文件,可通过C币或积分下载,没有C币或积分的朋友可在关注、点赞和评论博文后,私信发送您的邮箱,我会在第一时间发送给您。博主后面会有更多的分享,敬请关注哦!
    ?

    cs