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

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

猜你喜欢

转载自www.cnblogs.com/huangdengtao/p/11793110.html