12_经典问题解析一

关键词: const常量判别准则、引用的C++解释和编译器解释

1. 关于const的疑问:const什么时候为只读变量?什么时候是常量?

  • const常量的判别准则:
  1. 只有用字面量初始化的const常量才会进入符号表
  2. 使用其他变量初始化的const常量仍是只读变量
  3. volatile修饰的const常量不会进入符号表

总结:在编译期间不能直接确定初始值const标识符都被作为只读变量处理。

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

编程说明:const典型问题分析

#include 
#include 

using namespace std;

int main()
{
    const int x = 1;    // x为常量,因为x用字面量初始化, 编译期间能确定初始值,其值在符号表中,编译器也会为x分配一段内存空间
    const int& rx = x;  // rx为只读变量,其所对应的内存空间为编译器为x所分配的内存空间
    int& nrx = const_cast(rx);    // nrx消除了rx的只读属性,为一个普通的变量
    
    nrx = 5;
    
    cout << "x = " << x << endl;        // x的值在符号表中读取,因此输出为1
    cout << "&x = " << &x << endl;      // x的地址为编译器为x分配的内存空间
    cout << "rx = " << rx << endl;      // rx的值为内存空间中的值,由于nrx改变了内存空间的值,因此此处的rx的值为5
    cout << "&rx = " << &rx << endl;    // rx的地址为x的地址
    cout << "nrx = " << nrx << endl;    // nrx为普通变量,可以出现在赋值符号的左边进行赋值,赋值后,对应的内存空间中的值发生改变
    cout << "&nrx = " << &nrx << endl;  // nrx的地址为x的地址
    
    volatile const int y = 2;           // y为只读常量,其值可以通过指针或引用来改变
    int* p = const_cast(&y);      // 用指针p来指向y
    
    *p = 10;                            // 给*p赋值
    
    cout << "y = " << y << endl;
    cout << "*p = " << *p << endl;
    cout << "p = " << p << endl;
    
    char c = 'c';
    char& rc = c;
    const int& trc = c;     // 由于类型不同, 会生成一个新的只读变量。
    int& itrc = const_cast(trc);
    
    rc = 'a';
    itrc = 'd';
    
    cout << "c = " << c << endl;
    cout << "rc = " << rc << endl;
    printf("trc = %c\n", trc);  
    printf("itrc = %c\n", itrc);    
    
    printf("&c = %p\n", &c);    
    printf("&rc = %p\n", &rc);
    cout << "&trc = " << &trc << endl;
    cout << "&itrc = " << &itrc << endl;
    
    return 0;
}

输出结果:

x = 1
&x = 0xbfcd055c
rx = 5
&rx = 0xbfcd055c
nrx = 5
&nrx = 0xbfcd055c
y = 10
*p = 10
p = 0xbfcd0560
c = a
rc = a
trc = d
itrc = d
&c = 0xbfcd055b
&rc = 0xbfcd055b
&trc = 0xbfcd0564
&itrc = 0xbfcd0564

2. 关于引用的疑问

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

  • 指针是一个变量

    • 指针的值为一个内存地址,不需要初始化,可以保存不同的地址;
    • 通过指针可以访问对应内存地址中的值
    • 指针可以被const修饰成为常量或者只读变量
  • 引用只是一个变量的新名字

    • 对引用的操作(赋值,取地址等)都会传递到代表的变量上
    • const引用使其代表的变量具有只读属性
    • 引用必须在定义时初始化,之后无法代表其它变量。
  • 从使用C++语言的角度来看:引用与指针没有任何的关系,引用是变量的新名字,操作引用就是操作对应的变量;

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

  • 在工程项目开发中

    • 在进行C++编程时,直接站在使用的角度看待引用,与指针毫无关系,引用就是变量的别名
    • 在对C++代码进行调试分析时,一些特殊情况,可以考虑站在C++编译器的角度看待引用

编程说明:引用典型问题分析

#include 

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}; // &array[1] - &array[0] = ?  Expected ==> 4
                                // 在C语言中数组,数组是一片连续的存储空间,而此时的a, b, *pc是不同的存储区,内存地址不是连续的
    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;
}

总结: 在C++中不支持引用数组

3. 小结

  • 指针是一个变量
  • 引用是一个变量的新名字
  • const引用能够生成新的只读变量
  • 在编译器内部使用指针常量实现“引用”
  • 编译时不能直接确定初始值的const标识符都是只读变量

声明:此文章仅是本人在学习狄泰学院《C++深度解析教程》所做的笔记,文章中包含狄泰软件资料内容,一切版权归狄泰软件所有!
实验环境:gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3)

你可能感兴趣的:(12_经典问题解析一)