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引用能夠生成新的隻讀變量