天天看點

第12課 經典問題解析一

1. 關于const的疑問

(1)const常量的判别準則

  ①隻有用字面量初始化的const常量才會進入符号表,如const int i = 1;

  ②使用其它變量初始化的const常量仍然是隻讀變量。如const int a = b;//a為隻讀變量

  ③被volatile修飾的const常量不會進入符号表,如volatile const int i = 1;//這時會為i配置設定記憶體,且i每次都是從記憶體中取值。加const隻是說明i不能作為左值。

  ▲在編譯期間不能直接确定初始值的const辨別符,都被作為隻讀變量處理。

(2)const引用的類型與初始化變量的類型

  ①當用變量來初始化與const引用時,如果兩者類型相同,則初始化變量成為隻讀變量。

  ②當用變量來初始化與const引用時,如果兩者類型不同,則将生成一個新的變量,即引用的是另一個新變量,而不是原來的用來初始化引用的那個變量。

【程式設計實驗】const典型問題分析

#include <stdio.h>

int main()
{
    //實驗1:初始化變量的類型與引用類型相同時
    const int x = 1;
    const int& rx = x;//x與rx的類型相同,是以rx為隻讀變量,不能作為左值
                      //但本質上還是變量,引用x的記憶體值(而不是符号表中的值)

    int& nrx = const_cast<int&>(rx);//轉為普通引用

    nrx = 5;  //nrx與rx都引用了x的記憶體值

    printf("x = %d\n", x);     //1,從符号表中讀取
    printf("rx = %d\n", rx);   //5,從記憶體中讀取
    printf("nrx = %d\n", nrx); //5,從記憶體中讀取

    printf("&x = %d\n", &x);
    printf("&rx = %d\n",&rx);
    printf("&nrx = %d\n",&nrx); //x、rx、nrx位址相同

    //實驗2:初始化變量的類型與引用類型不同時
    char c = 'c';
    char& rc =c;
    const int& trc = c;//c與trc類型不一緻,則會生成一個新的變量,然後trc引用這個新的變量
    
    rc = 'a';

    printf("c = %c\n", c);  //c
    printf("rc = %c\n",rc); //c
    printf("trc = %c\n",trc);//a

    printf("&c = %p\n", &c); 
    printf("&rc = %p\n",&rc); //rc與c的位址相同
    printf("&trc = %p\n",&trc);//trc是一個新的位址

    //實驗3:volatlie
    volatile const int y = 2; //volatile修飾,分為y配置設定記憶體
    int* p = const_cast<int*>(&y);//因y被const修飾,不能作為左值

    *p = 6; //因y不能作為左值,用來代替y = 6;這樣的寫法

    printf("y = %d\n", y);//6,volatile訓示y得從記憶體中讀取
    printf("p = %p\n", p);//y的位址

    const int z = y; //用變量初始化const常量,z不會進入符号表,z配置設定記憶體

    p = const_cast<int*>(&z);
    
    *p = 7;

    printf("z = %d\n", z);//7,因z沒進入符号表
    printf("p = %p\n", p);//z的位址

    return 0;
}      

2. 關于引用的疑問

(1)指針與引用的不同

指針 引用
初始化 值是一個記憶體位址,不需要初始化 必須在定義時初始化,之後無法代表其它變量
通路記憶體 通過指針可以通路對應記憶體位址中的值 對引用的操作(指派,取位址等)都會傳遞到其代表的變量上。
const修飾 被const修飾成常量或隻讀變量。 如const int* p;//p const引用,表示其代表的變量具有隻讀屬性。如,const int& a等價于const int* const a;

(2)從使用C++語言的角度來看,引用與指針沒有任何關系。引用是變量的新名字,操作引用就是操作對應的變量。當進行C++程式設計時,直接站在使用的角度看待引用,與指針毫無關系,引用就是變量的别名。

(3)從C++編譯器的角度來看,在編譯器内部,使用指針常量來實作“引用”。是以,“引用”在定義時必須初始化。當對C++代碼進行調試分析時,一些特殊情況,可以考慮站在C++編譯器的角度看待引用。

【程式設計實驗】引用典型問題分析

#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各成員初始化為變量a,b,*pc等記憶體的引用
    SV sv = {a, b, *pc};
    printf("&sv.x = %p\n", &sv.x);//變量a的位址,全局區
    printf("&sv.y = %p\n", &sv.y); //變量b的位址,棧
    printf("&sv.z = %p\n",&sv.z);   //new出來的位址,堆

    //在C++中沒有“引用數組”的概念,請看如下分析
    //對于數組而言,其記憶體是連續分布的。當進行&array[1] - &array[0]
    //表示前後兩個元素的位址相差的值,應等于sizeof(元素的類型)。
    //但如果允許定義“引用數組”的話,如下面語句,&array[1]表示第1個元素
    //的位址,即元素b的位址(&b),而&array[0]表示&a,顯然這兩個位址是不連續的。
    //是以int& array[]={a, b, *pc};//這樣的定義是錯誤的,C++裡不支援“引用數組”

    return 0;
}      

3. 小結

(1)指針是一個變量,而引用是一個變量的新名字

(2)const引用能夠生成新的隻讀變量

繼續閱讀