首先我們我們先來看乙個例子:
for (int i = 0; i < 10; ++i)
上面的這個10在這裡迴圈裡面代表的是什麼意思呢?這個迴圈在做什麼事情呢?也就是說10這個數字的作用何在?在這裡,我們將這種不能表示任何意義的數字(比如這裡的10)稱之為魔數(magic number)。magic number在程式維護,程式理解上面都是一塊堵路石。假如我們在程式裡面要把10這個數字更改為20,要是只有單單只有該地方用到了magic number 10,那麼改起來是比較容易的,那要是有一百處都寫了10這個magic number呢?那豈不是要更改一百次?要是有些**段的10是用於其他目的呢?一不小心改錯了,程式就有可能出錯。這樣又難於理解又難於維護的程式對程式猿也算是種折磨。那有沒有比較好的方法呢?答案是肯定的。
我們下面來看一下這段**:
int eventnumber = 10;
for (int i = 0; i < eventnumber; ++i)
上面這段程式看起來就沒有那麼的費勁了,i
但是上面的**存在乙個問題,要是在程式執行中不小心更改了eventnumber的值,但是我們是不希望eventnumber更改的,那有什麼辦法可以避免這種情況呢?那就輪到const限定符上場了,將eventnumber定義為const int eventnumber =10;那麼就避免了不小心修改了eventnumber的值了,下面我們來了解一下const限定符的一些特性:
const限定符所修飾定義的物件在定義以後就不能再賦值(除非const_cast來解除限定),所以const限定符在定義的時候就需要初始化!
比如:const std::string str = "hello";//ok
const int i , j=0;//error,i沒有進行初始化,乙個變數沒有進行初始化,那麼這個在沒有進行賦值之前事沒有任何意義的
在全域性作用於中定義非const全域性變數,那麼這個程式預設是extern型別的,表明整個程式都可以訪問:
int a =10;
extern int a ;
但是對於const物件就不一樣了,如果沒有extern限定符顯式的修飾說明,那麼在全域性作用域宣告的const變數是在兌現的檔案的區域性變數,不可被其他檔案訪問:
const int a =10;//作用域限定於file1.cc裡面 就像普通變數的static修飾符一樣
extern const int a ;//error,聯結器不能連線file1.cc裡面的const變數
如果想要file2.cc能夠對file1.cc裡面的a變數具有訪問許可權,那麼就要顯式的為const變數加上ertern,下面的程式就可以正常執行:
extern const int a =10;//ok
extern const int a;//ok
這裡有一點就是需要注意的:
在file2.cc裡面不要寫成extern int a 這種形式,我在g++上面測試,雖然不加const限定符也可以編譯通過,但是!一旦對變數a進行任何修改的話,馬上就會段錯誤 (核心已轉儲),所以還是在加上const限定符的好!
在傳統的c語言裡面是沒有引用這種說法的,如果想要訪問操作一塊記憶體塊,要麼用這塊記憶體塊繫結的那個唯一的變數名,要麼使用指向這塊位址的指標來進行操作,但是c++裡面就多了一種新的方法來訪問操作一塊記憶體塊,那就是引用,上面我們說過c語言裡面乙個記憶體快只有乙個變數名繫結,但是在c++裡面就可以用多個變數名來繫結同一塊記憶體,也就是變數的另外乙個名字
int val = 1024;
int & refval =ival;
refval就是指向val的引用!
下面介紹引用的一些特性:
引用只是物件(記憶體中有型別的區域)的乙個別名,作用在引用上的所有操作事實上都是操作在引用繫結的物件上,比如下面的例子:
初始化是指明引用指向那個物件的唯一方法!
const引用是指向const物件的引用。
const int val = 100;
const int & refval = val;//ok
int & refval = val;//error,val是乙個const物件,卻用乙個非const引用去繫結這個物件,那麼就有可能通過該引用修改這個const物件,所以這是錯誤的!
下面我們看兩個例子:
例子1:
float number = 10;
int & intnumber = number;
編譯結果為:
error: invalid initialization of reference of type 『int&』 from expression of type 『float』
///但是如果是這樣的呢?
float number = 10;
const int & intnumber = number;
編譯順利通過。
例子2:
int & number = 10;
編譯結果:
invalid initialization of non-const reference of type 『int&』 from an rvalue of type 『int』
const int & number = 10;
編譯通過。
那麼為什麼const引用和非const引用之間會存在如此的差別呢?我們觀察下面的例子:
double dval = 3.14;
const int & ri = dval;
編譯器將會將上面的**轉為:
int temp = 3.14;
const int & ri = 3.14;
因此每次在建立乙個const引用時都會建立乙個新的臨時變數(新的物件),將const對引用繫結到新建立的這個temp物件上。那到底是不是這樣的呢?
我們通過**說話
code1:
int inumber = 10;
int & refinumber = inumber;
printf("inumber address:%p\nrefinumber address:%p\n",&inumber , &refinumber);
執行結果為:
inumber address:0xbfe22718
refinumber address:0xbfe22718
可知inumber和refinumber都指向同乙個物件! /
code2:
int inumber =10;
const int & refinumber = inumber;
printf("inumber address:%p\nrefinumber address:%p\n",&inumber , &refinumber);
執行結果為:
inumber address:0xbf8640f8
refinumber address:0xbf8640f8
發現位址並無什麼變化。
code3:
int inumber =10;
const float & refinumber = inumber;
printf("inumber address:%p\nrefinumber address:%p\n",&inumber , &refinumber);
執行結果為:
inumber address:0xbfd2fd24
refinumber address:0xbfd2fd28
發現現在的位址已經發生變化了,說明新建立了乙個物件!
///所以const物件並不是每種情況下都建立乙個臨時的變數,只有在引用型別和物件型別不同時或者直接初始化為乙個常量才會新建立臨時物件!
const引用重要特性:非const引用只能繫結到與該引用同型別的物件。const引用則可以繫結到不同當型別相關的物件或者繫結到右值!
C 之const限定符
const的特點 用const加以限定的變數,無法改變。由於const物件定義之後就無法改變,所以必須對其進行初始化。const物件的常量特徵僅在嘗試改變它的時候表現出來,其他時候和變數無異。const初始化 const int bufsize 512 bufsize無法再改變const物件通常只在...
C 的const限定符
const限定符總是讓人很頭疼,下面講解一下幾個比較容易混淆的概念 對常量的引用 常量引用 一般情況下,引用的型別要與其所引用的物件的型別一致,其中的例外情況就是,當初始化常量引用時,允許用任意表示式作為初始值,只要改表示式能轉換成引用的型別即可。const int i 1 const int ri...
C 的const限定符
一 const常量 const int a 123 編譯時初始化 const int a get size 執行時初始化 a 111 錯誤,a是常量物件,不能改變了 const int b 錯誤 二 對const和const引用的初始化 初始化常量或常量引用時允許用任意表示式作為初始值,只要該表示式...