const是C語言中總結
1.修飾的變量,使其具備常屬性,使變量的值不能直接被改變。可是能夠經過指針來間接的修改變量的值。
2.便於進行類型檢查(在編譯時進行類型檢查),使編譯對處理內容有更多的瞭解,保護被修飾的東西,防止被意外修改,加強程序的健壯性。
3.方便的進行參數的調整和修改(相似於宏定義)
做用1說明:
修飾的變量,使其具備常屬性,使變量的值不能直接被改變。可是能夠經過指針來間接的修改變量的值
例如:ios
const int t=10; //在之後的代碼中,程序不可直接對i進行修改 //可是可經過指針來間接的修改i變量中存的值 t=2; //會報錯 int *p=(int *)&t; *p=2; //在此處就將i中的值存成2了
const修飾指針變量:c++
int main() { int a = 10; const int *p = &a; //const修飾int *,即p的指向,於是p指向的內容即經過pa解引用後不能被修改,可是p中存的內容能夠改變,即p的指向能夠改變 int * const q=&a; //const修飾*,即q變量,於是q裏存的內容不能變,即q的指向不能改變,可是q指向的內容即a中的內容能夠修改。 p++;//正確 (*p)++;//錯誤 q++;//錯誤 (*q)++;//正確 return 0; }
因此看const修飾誰,要看const右面有什麼
好比:
int **const* p; 則經過*p來修改對應的內容則報錯安全
int **const** p; 則經過**p來修改內容則會報錯ide
經過const的特性,const能夠在不少地方派上用場
好比在傳參時,不想經過函數來改變實參值,在傳實參地址時,形參接收在前可加const修飾,這樣就不會在函數裏經過解引用來修改實參值了函數
在c++中:
1.const修飾變量的用法和做用與c語言同樣,可是有一點不一樣性能
#include <iostream> using namespace std; int main() { const int a = 1; int* p = (int *)(&a); *p = 2; cout << "value of p: " << *p << endl; cout << "value of a: " << a << endl; cout << "address of p: " << p << endl; cout << "address of a: " << &a << endl; return 0; } 輸出 /*value of p: 2 value of a: 1 address of p: 0x7fbffff7fc address of a: 0x7fbffff7fc
由答案可知,a並無像c語言中同樣,被p修改成2,這是爲何呢?
緣由: const int a實際上是保存在符號表中,無內存地址,但本身對a進行&a,那麼編譯器會爲a分配一個地址,但取a的值依然是從符號表中取值,而用指針int *p=&a;
*p=4這個值是改變a的內存所表示值,不會改變符號表中a的值。this
#include <iostream> using namespace std; const int a = 3; //此時a是全局變量 int main() { //const int a = 3; int* p = const_cast<int*>(&a); *p = 4; cout << "value of p: " << *p << endl; cout << "value of a: " << a << endl; cout << "address of p: " << p << endl; cout << "address of a: " << &a << endl; return 0; }
輸出結果
會發生如此運行時錯誤
因而可知,在c++中全局const變量和局部const變量的編譯器處理的方法是不同的。由於全局const變量是不分配內存地址的,它編譯器放置在符號表中做爲編譯期常量,全局const變量放在只讀數據段中,受到只讀數據段的權限保護,當你修改一個只讀數據段中的內容時,會獲得一個運行時錯誤。而局部const變量是放在堆棧之中,由於在內存中有地址,經過修改地址中的值能夠達到修改const所指內存中值的目的。spa
2.此外,在c++中,const還可用來修飾成員函數,其用法是放在形參列表以後,
用來修飾隱式傳入構造函數中的this指針,代表在函數調用的過程當中,不可對this指向的內容進行修改,即不可修改調用這個構造函數對象中的內容。
被const修飾的成員函數,稱做爲const類型的成員函數
例如:指針
class Date { public: Date(int year = 1900, int month = 1, int day = 1) { _year = year; _month = month; _day = day; cout << "Date(int,int,int):" << this << endl; } // 在const成員函數中,不能修改類的任何成員變量 void PrintDate()const { //_year++; //即this->_year++; 會報錯 // 在函數被修飾後,this的類型爲 const Date* const (由於this指針原本就是const型的this不可修改指向,後面的const代表this指向裏的內容也不可修改) _day++; //√ cout << _year << "-" << _month << "-" << _day << endl; } private: int _year; int _month; mutable int _day; //在成員變量名前加mutable關鍵字後,成員函數即便加const也可修改_day的值 }; int main() { Date d1; d1. PrintDate(); }
用const修飾成員函數有如下注意事項:
1>const不可修飾其餘類外函數(對有this的函數纔有用)。不可調用構造函數,由於構造函數目的就是要修改爲員變量。
2>const對象不能夠調用非const成員函數。由於普通成員函數是能夠修改爲員變量的,若是容許修改,拿不可修改的const對象就會被修改了,不安全。
3>非const對象能夠調用const成員函數。由於普通變量可讀可寫,const函數只容許對調用對象進行讀,所以沒有什麼不可。
4>const成員函數不能夠調用非const成員函數。普通函數可對對象進行修改,在調用普通函數時可能會修改對象,所以const成員函數不能調用非const成員函數。
5>非const成員函數能夠調用const成員函數調試
(1) 編譯器處理方式不一樣
define宏是在預處理階段展開。
const常量是編譯運行階段使用。
(2) 類型和安全檢查不一樣
define宏沒有類型,不作任何類型檢查,僅僅是展開。
const常量有具體的類型,在編譯階段會執行類型檢查。
(3) 存儲方式不一樣
define宏僅僅是展開,有多少地方使用,就展開多少次,不會分配內存。
const常量會在內存中分配(能夠是堆中也能夠是棧中)
const修飾能夠節省空間,避免沒必要要的內存分配(與宏定義的本質區別)
宏的優勢:1.加強代碼的複用性。2.提升性能。缺點:1.不方便調試宏。(由於預編譯階段進行了替換) 2.致使代碼可讀性差,可維護性差,容易誤用。 3.沒有類型安全的檢查