use const whenever possibleios
它容許你指定一個語義約束(也就是制定一個不應被改動的對象,而編譯器會實施這項約束。c++
你能夠用它在classes外部修飾global或者namespace做用域的常量或者修飾文件,函數,或
區塊做用域中被聲明爲static對象。你也能夠用它修飾classes內部的static和non-static成員變
量。面對指針,你也能夠指出指針自身,指針所指物,或二者都(或都不)是const函數
例如: char greet[] = "Hello"; char *p1= greet; // non-const pointer, non-const data 指針和指針指向地址的內容均可以改變 const char *p2 = greet; // non-const pointer, const data 指針的內容能夠改變,指針指向地址的內容不能改變 char* const p3 = greet; // const pointer, non-const data 指針的內容不能改變,指針指向地址的內容改變 const char* const p4 = greet; // const pointer, const data 指針的內容不能改變,指針指向地址的內容不能改變 //上面幾個例子展示了const用於指針時的幾種不一樣狀況,在實際狀況下根據本身須要使用。
const能夠和函數參數,函數返回值,函數自身(成員函數)產生關聯。
舉個例子:學習
#include <iostream> class Wid{ public: void get(int &a){ if(a = 1){ // 將 == 誤寫成 = std::cout << "in get() the a is " << a << std::endl; } } }; int main(){ Wid w; int a = 2; // a最開始的值是2 w.get(a); std::cout << "the a is " << a << std::endl; return 0; } 運行結果: [m@m ~/practice]$ ./7.out in get() the a is 1 the a is 1 // 從以上結果咱們能夠知道若是咱們在寫代碼時,若是將==誤寫成=,那麼可能就會將一些咱們 // 不想改變的值給改變,a就是這樣的。
因此有時候const是咱們程序代碼的幫手,能夠幫咱們檢查程序中本不應發生的錯誤。this
// 給int &a 前面加上const,其餘不變,不出意外咱們能夠看到程序報錯的消息 #include <iostream> class Wid{ public: void get(const int &a){ if(a = 1){ std::cout << "in get() the a is " << a << std::endl; } } }; int main(){ Wid w; int a = 2; w.get(a); std::cout << "in main a is " << a << std::endl; return 0; } 運行結果: [m@m ~/practice]$ !clang clang++ 7.cpp -o 7.out 7.cpp:6:10: error: cannot assign to variable 'a' with const-qualified type 'const int &' if(a = 1){ ~ ^ 7.cpp:5:23: note: variable 'a' declared const here void get(const int &a){
1 error generated. #### const成員函數 const做用於成員函數中時,是不可改變成員變量的,可是全局變量,全局靜態變量,包括還有類中的類靜態成員變量都是能夠 被常成員函數修改的。 爲何說const成員函數比較重要呢?有兩個緣由: 1.它可讓類知道那些函數是能夠修改對象內容(成員變量的,那些是不能夠的。 2.它們是操縱const對象成爲可能。 // const做用於成員函數中時,是不可改變成員變量的 #include <iostream> class Wid{ public: Wid(int i){ a = i; } void get() const{ a++: // a是成員變量,是不能夠修改的 } private: int a; }; int main(){ Wid w(1); w.get(); return 0; } 運行結果: [m@m ~/practice]$ !clang clang++ 7.cpp -o 7.out 7.cpp:9:6: error: cannot assign to non-static data member within const member function 'get' a++: ~^ 7.cpp:8:8: note: member function 'Wid::get' is declared const here void get() const{ ~~~~~^~~~~~~~~~~ 1 error generated. 關於第二點,若是兩個成員函數只是常量性不一樣,能夠被重載,能夠使用const修飾其中一個函數,用來區分重載 #include <iostream> #include <string.h> class Wid{ public: Wid(std::string s){ text = s; } char& operator[](std::size_t position){ std::cout << "ordinary object" << std::endl; return text[position]; } const char& operator[](std::size_t position) const { std::cout << "const object" << std::endl; return text[position]; } private: std::string text; }; int main(){ Wid w("hello"); // 通常對象 const Wid w1("world"); // 常對象 // w[1] = 'x'; //能夠修改 // w1[2] = 'x'; // 不能夠修改,因爲w1是常對象,調用常函數,返回的是const char &,因此修改它是錯誤的。 w[1]; w1[1]; return 0; } 運行結果: ordinary object const object 能夠看到兩個重載操做符調用了不一樣的函數。 隨着繼續學習咱們能夠思考一下是否常函數真的不能修改爲員變量?答案是否認的。 **利用c++中一個與const相關的擺動場:mutable(可變的),能夠實如今常函數中修改爲員變量。** #include <iostream> class Wid{ public: Wid(int i){ a = i; } void change() const { a++; std::cout << "the a is " << a << std::endl; } private: mutable int a; }; int main(int argc, char *argv[argc]) { Wid w(1); w.change(); return 0; } 運行結構: the a is 2 // 能夠看到a確確實實被修改了,但沒什麼必要就不要改變常函數的行爲了,容易使代碼出現混亂。 #### 在const和non-const成員函數中避免重複 首先貼一段上文的代碼片斷: char& operator[](std::size_t position){ ... // 一些處理代碼 return text[position]; } const char& operator[](std::size_t position) const { ... //同上,相同的處理代碼 return text[position]; } 咱們能夠看到除了函數名不一樣,函數體的代碼都相同(爲了演示,實際不必定相同),形成了代碼重複, 爲了不這種狀況,咱們能夠使用另一種方法,來實如今一個函數體中調用另外一個函數中的代碼 #include <iostream> #include <string.h> class Wid{ public: Wid(std::string s){ text = s; } char& operator[](std::size_t position){ // 代碼有兩次轉型,第一次:將*this 從 static_cast<const Wid&> 是爲了將Wid& 轉換爲const Wid& // 第二次: 將返回值類型從const char & 轉換爲char & return const_cast<char&>(static_cast<const Wid&>(*this)[position]); } const char& operator[](std::size_t position) const { return text[position]; } private: std::string text; }; int main(){ const Wid w1("world"); std::cout << "the w1 is " << w1[1] << std::endl; return 0; } 運行結果: the w1 is o ***咱們在non-const函數中調用了const函數來避免了代碼的重複,那是否能夠反向調用,使其在const函數中調用non-const函數呢? 最好不要,由於const函數承諾毫不改變函數的邏輯狀態,而咱們在const函數中調用non-const函數違背了這一準則,由於曾經承 諾的那個對象被修改了*** **總結:** 1.將某些東西聲明爲const,可幫助編譯器檢測出錯誤。const可做用於任何做用域對象,函數參數,函數返回類型,成員函數本體。 2.const和non-const成員函數有着實質的相同實現時,令non-const 調用 const 的版本可避免代碼重複。 有哪些不對的地方,歡迎指正。