概念安全
const就是爲了直接表達「不變化的值」這一律念。也就是說該值只可讀,不可直接寫。
因爲不能夠修改,因此const常量在聲明的時候必須初始化函數
const int a; //error extern const int ext_a;
做用this
const int a = 4 ; //a = 5; //error
void fun1(const int a) { //a=5; } void fun2(const ClassA& a) { //a.xx=xx }
class ClassA { public: void funA() {
//... } void funA() const { //... } };
const與指針spa
The C++ Programming Language裏面給出過一個助記的方法: 把一個聲明從右向左讀。翻譯
char * const p1; //p1 is a const pointer to char const char *p2; //p2 is a pointer to const char const char * const p3; //p3 is a const pointer to const char
Effective C++一樣給出了一種方式,若是關鍵字const在星號的左邊,表示被指物是常量;若是出如今星號右邊,表示指針自身是常量;若是出如今兩邊,表示被指物和指針兩者都是常量。其實指針只要分清指針自己與所指向的內容便可。我的以爲不用糾結與有些書上的叫法什麼「指針常量」,「常量指針」,這都是在翻譯的過程當中帶來的歧義。指針
如p1是一個const pointer,因此在聲明的時候必須初始化,不然編譯不經過,而*p1則是char類型。
p2是一個pointer但不是const,*P2纔是const類型,因此p2能夠不用初始化。調試
那麼p1聲明指向的爲char 是否能夠指向const char 呢?p2聲明指向的爲const char 是否能夠指向char類型呢?
code
const char ca = 'a' ; char b= 'b'; char *p; //p=&ca; //error p=&b; char * const p1=&b; //char * const p1=&ca; //error const char *p2; p2=&ca; p2=&b; //ok const char * const p3=&b; //ok
由於對承諾不修改的內容要被修改,確定是有問題的;但對可修改的內容不作修改沒有任何問題。如上面ca不可修改,*p能夠修改,因此p=&ca錯誤;而b能夠修改,*p1不能夠修改,p=&b對b不會形成不良影響,因此能夠經過。對象
那麼是否是非const類型能夠直接賦值與const類型呢?而const類型不能直接賦值與非const類型呢?blog
ClassA ca; const ClassA cst_b; ClassA cc=cst_b; //copy構造函數能夠理解 ClassA c2; c2=cst_b; //?? const ClassA cst_d=ca; int a=1; const int b=a; int c=b; //??
以上代碼徹底能夠編譯經過,那該怎麼解釋呢?我的理解爲若是賦值後的對象不對原對象代碼不良影響,都是能夠經過的。如int c=b;c的修改不會修改b;c2=cst_b,調用ClassA的賦值操做ClassA& operator=(const ClassA&),也一樣不會對原cst_b修改。
const與引用
引用與指針有所不一樣,由於引用自己能夠看做是一個常量指針,引用在聲明是必須初始化,且不能夠在引用值其餘對象。因此引用只存在一種形式。const type& 而type& 與type& const 等價。const 引用主要運用在函數的參數傳遞方面。Effective C++ 第20條 Perfer pass-by-reference-to-const to pass-by-value.
int a; int & ref1=a; const int & ref2 =a; int & const ref3=a; //不必
const與函數
函數與const 的關係能夠從三部分來看,返回值、參數、函數自身
class ClassA { public: int a; ClassA():a(1) { } const int funA() //沒意義,由於返回值自己就沒法修改 與int funA()同樣,並且也不存在funA()=4這種寫法 { return a; } int * const funB() //與funA同樣,const的限定的是返回值的指針,也沒法修改 。與int * funB() 同樣 { return &a; } const int * funC() //const修飾的是返回指針所指內容,因此該函數的接收這也必須爲const int*類型 { return &a; } const int &funD() //返回引用,該引用不能夠修改 { return a; } void test() { int re=funA(); int *p= funB(); //int *p1=funC(); //error const int *p2=funC(); //int& c=funD(); //error const int& a2=funD(); } };
funA、funB其實實際意義都不大,由於不論返回值是否是const類型,函數調用者都不可能修改返回值的實際值。而函數調用者該不應用const與函數自己不要緊。
cosnt自定義類型返回值,每每能夠下降因函數調用者錯誤而形成的之外,而又不至於放棄安全性和高效性
ClassA funCA() { ClassA a; return a; } int _tmain(int argc, _TCHAR* argv[]) { ClassA ca; funCA()=ca; }
funCA()=ca;這句話具體有什麼實際意義呢?沒意義,可是就是能夠編譯經過,此時就能夠將funCA返回值限定爲const ClassA,這樣的寫法首先編譯器都不經過。
int funA(const int a); int funB(int * const p); int funC(const int *p); int funD(const int& ra);
class ClassA { public: int a; ClassA():a(1) { } void fun() { a=5; cout<<"this is not a const function"<<endl; } void fun() const { // a=5; //error cout<<"this is a const function"<<endl; } }; int _tmain(int argc, _TCHAR* argv[]) { ClassA ca; ca.fun(); //this is not a const function const ClassA cb; cb.fun(); //this is a const function }
const對象只能調用const函數,且const函數不能對成員函數作修改。若將void fun()函數刪掉,則編譯不經過錯誤提示:ClassA::fun」: 不能將「this」指針從「const ClassA」轉換爲「ClassA &;若將void fun() const 函數刪掉,則ca.fun()調用const fun。
今天快下班了,先寫這些吧,明天補充總結!