• 第12课.经典问题解析(const;指针和引用)


    问题1:const什么时候为只读变量?什么时候是常量?

    const常量的判别准则:
    a.只有用字面量初始化的const常量才会进入符号表(直接初始化过的const为常量)
    b.被使用其他变量初始化的const常量仍然是只读变量(间接初始化的const为只读变量)
    c.被volatile修饰的const常量不会进入符号表(volatile:易变的。每次都要去内存中取出值。所以也是只读变量。voaltile易变的在这里决定了cosnst不可能是一个常量;const则说明在当前的作用域当中,修饰的变量不能出现在赋值符号的左边(只读))
    总的来说:在编译期间不能直接确定初始值的const标识符,都被作为只读变量处理

    const引用的类型与初始化变量的类型
    类型相同:初始化变量为只读变量
    类型不同:生成一个新的只读变量(类型为左值中的类型)

    #include <stdio.h>
    
    int main()
    {
    	const int x = 1;            //常量
    	const int& rx = x;          //只读变量
    	
    	int& nrx = const_cast<int&>(rx);
    	
    	nrx = 5;
    	
    	printf("x = %d
    ", x);            //1 x被写到符号表中
    	printf("rx = %d
    ", rx);          //5
    	printf("nrx = %d
    ", nrx);        //5
    	printf("&x = %p
    ", &x);          //地址相同
    	printf("&rx = %p
    ", &rx);
    	printf("&nrx = %p
    ", &nrx);
    	
    	volatile const int y = 2;          //只读变量
    	int* p = const_cast<int*>(&y);
    	
    	*p = 6;
    	
    	printf("y = %d
    ", y);        //6
    	printf("p = %p
    ", p);           
    	
    	const int z = y;            //只读变量
    	
    	p = const_cast<int*>(&z);
    	
    	*p = 7;
    	
    	printf("z = %d
    ", z);    //7
    	printf("p = %p
    ", p);
    	
    	char c = 'c';            
    	char& rc = c;
    	const int& trc = c;          //这里const引用的初始化时的类型与初始值类型不同,所以这里被定义成了一个新的只读变量。此时const int& trc = c;相当于给一个名为trc空间的内存赋值了‘c’。
    	
    	rc = 'a';           //修改不会影响到trc
    	
    	printf("c = %c
    ", c);
    	printf("rc = %c
    ", rc);
    	printf("trc = %c
    ", trc);
    	
    	return 0;
    }
    

    问题2:引用于指针有什么关系?如何理解“引用的本质就是指针常量”?

    指针:
    指针是个变量。
    a.值为一个内存地址,不需要初始化,可以保存不同的地址。
    b.通过指针可以访问对应内存地址中的值
    c.指针可以被const修饰成为常量或者只读变量。

    引用
    引用只是一个变量的新名字。
    a.对引用的操作(赋值,取地址)都会传递到代表的变量上
    b.const引用使其代表的变量具有只读属性(const修饰的引用是只读变量,但指针还有常量)
    c.引用必须在定义时初始化,之后无法代表其他变量。

    从使用c++语言的角度来看
    a.引用与指针没有任何关系
    b.引用是变量的新名字,操作引用就是操作对应的变量

    从c++编译器的角度来看
    a.为了支持新概念“引用”必须要一个有效的解决方案
    b.在编译器内部,使用指针常量来实现“引用”
    c.因此“引用”在定义时必须初始化

    在工程项目开发中
    a.当进行c++编程是,直接站在使用的角度看待引用,与指针毫无关系,引用就是变量的别名
    b.当对c++代码进行调试分析时,一些特殊情况,可以考虑站在c++编译器的角度看待引用。

    思考:下面的代码有问题吗?

    int a = 1;
    int b = 2;
    int *pc      = new int(3);        //定义一个指针,分配空间并赋值
    int& array[] = {a, b, *pc};
    

    测试:

    #include <stdio.h>
    
    int a = 1;
    
    struct SV
    {
    	int& x;
    	int& y;
    	int& z;
    };
    
    int main()
    {
    	int b = 2;
    	int* pc = new int(3);
    	SV sv = {a, b, *pc};
    	int& array[] = {a, b, *pc}; // error &array[1] - &array[0] = ?  Expected ==> 4
    	
    	printf("&sv.x = %p
    ", &sv.x);
    	printf("&sv.y = %p
    ", &sv.y);
    	printf("&sv.z = %p
    ", &sv.z);
    	
    	delete pc;
    	
    	return 0;
    }
    

    数组中的每一个元素都是顺序存放的,也就是说他们的地址是递增的。可从测试结果中看到。&array[1] - &array[0] = ? Expected ==> 4。所以c++中不支持引用数组。当然结构体支持(struct SV)。

  • 相关阅读:
    Asp.Net多线程用法1
    Asp.Net操作FTP方法
    django 利用PIL 保存图片
    django —— Celery实现异步和定时任务
    豆瓣源安装requirements.txt
    一个有趣的python排序模块:bisect
    Python 多线程
    python list元素为dict时的排序
    python版本坑:md5例子(python2与python3中md5区别)
    单独的 python 脚本文件使用 django 自带的 model
  • 原文地址:https://www.cnblogs.com/huangdengtao/p/11793110.html
Copyright © 2020-2023  润新知