盡可能使用const

2021-07-10 13:18:00 字數 4154 閱讀 5073

const定義語義約束:制定乙個不被改動的物件,編譯器會強制實施這項約束。只要某值保持不變時事實,就應該確實說出來,這樣編譯器可以確保這項約束不違反。

const多才多藝:可以用在classes外部修飾global或namespace作用域中的常量,或修飾檔案、函式、或區塊作用於中被宣告為static的物件。它可以用來修飾classes內部的static或non-static成員變數。面對指標,也可以指出指標本身、指標所指之物、或兩者都不是const

char greet = "hello";

char *p = greet; // 非常量指標,非常量資料

const char *p = greet; // 非常量指標,常量資料

char * const p = greet; // 常量指標,非常量資料

const char * const = greet; // 常量指標,常量資料

如果關鍵字const出現在*號左邊,表示被指物是常量;如果出現在*號右邊,表示指標自身是常量;如果出現在*號兩邊,表示被指物和指標兩者都是常量。

如果被指物是常量,可以將關鍵字const寫在型別之前,也可以寫在型別之後,*號之前。具體如下:

void f1(const widget *pw);  // f1獲得乙個指標,指向乙個常量的widget物件

void f1(widget const *pw); // f2獲得乙個指標,指向乙個常量的widget物件

stl迭代器以指標為根據塑模出來,故迭代器作用是t *指標。宣告迭代器為const就像宣告指標為const一樣(宣告乙個t *const),表示這個迭代器不的指向不同的東西,但它所指的東西的值可以改動。如果希望迭代器所指的東西不可被改動,則定義為const t *指標即可。舉例如下:

std::vectorvec;

const std::vector::iterator iter = vec.begin(); // iter為t * const

*iter = 10; // 正確可以改變

++iter; // 錯誤,iter是const不能改變

std::vector::const_iterator citer = vec.begin(); // citer為const t*

*citer = 10; // 錯誤,*citer是cosnt

++citer; // 正確,可以改變citer

const最具威力的用法是面對函式宣告時的應用。在乙個函式宣告式內,const可以和函式返回值、各引數、函式自身(如果是成員函式)產生關聯。令函式返回乙個常量值,往往可以降低因客戶錯誤而造成的意外,而又不至於放棄安全性和高效性。乙個良好的使用者自定義型別的特徵是他們避免無端地與內建型別不相容。而對於const引數,就像local const物件一樣,在必要的時候使用它們。除非有需要改動引數或local物件,否則請將他們定義為const。可以防止意外輸入。舉例如下:

class rational;

const rational operator* (const rational &lhs, const rational &rhs);

const成員函式

將const實施於成員函式目的,是為了確認該成員函式可作用於const物件身上。這類函式重要原因:1)它們使class介面比較容易被理解。得知哪個函式可以改變物件內容,哪個函式不可以很重要。2)它們使操作const成為可能。這是**高效的關鍵。c++高效的乙個根本方法是pass by reference-to-const方式傳遞物件。但前提是const成員函式可用來處理取得的const物件。

c++重要特性:兩個成員函式如果只是常量性不同,可以被過載。舉例如下:

class textblock

char &operator(std::size_t position) // operator for non-const物件

private:

std::string text;

};textblock的operators可以被這麼使用:

textblock tb("hello");

std::cout << tb[0]; // 呼叫non-const textblock::operator

const textblock cbt("world");

std::cout << ctb[0]; // 呼叫const textblock::operator

真實程式中const物件大多用於passed by pointer-to-const或passed by reference-to-const傳遞結果。可以使用下面呼叫:

void print(const textblock& ctb)   // ctb為const

只要過載operator並對不同的版本給於不同的返回型別,就可以令const和non-const textblocks獲得不同的處理:

std::cout << tb[0];    // 正確,讀non-const textblock

tb[0] = 'x'; // 正確,寫non-const textblock

std::cout << ctb[0]; // 正確,讀const textblock

ctb[0] = 'x'; // 錯誤,寫const textblock

上面錯誤原因在於對乙個const版本的operator返回值實施賦值動作錯誤。注意:non-const operator的返回型別是個reference to char,不是char。如果是char,則tb[0] = 『x』將不能通過編譯。原因是函式返回型別是個內建型別,改動函式返回值從來就不合法。

bitwise const:乙個更改了「指標所指之物」的成員函式雖然不能算是const,但如果只有指標(而非其所指物)隸屬於物件,那麼此函式為bitwise const不會引發編譯器異議。

logical const:乙個const成員函式可以修改它所處理的物件內的某些bits,但只有在客戶端偵測不出的情況下才得如此。

利用c++的乙個與const相關的擺動場,mutable(可變的)。mutable釋放掉non-static成員變數的bitwise constness約束。

在const和non-const成員函式中避免重複

令non-const呼叫其const兄弟是乙個避免**重複的安全做法——即使過程中需要乙個轉型動作。舉例如下:

class textblock

char& operator(std::size_t position) // 現在只呼叫const op

}

上例中有兩個轉型動作。第一次用來為*this新增const(這使接下來呼叫operator時得以呼叫const版本),第二次則是從const operator的返回值中移除cosnt。它可以避免**重複效果。它運用const operator實現了non-const版本。**注意:**const成員函式承諾絕不改變其物件的邏輯狀態,non-const成員函式卻沒有這版承諾。如果在const中呼叫了non-const函式,就是冒了這樣的風險:你曾經承諾不改動的那個物件被改動了。const成員函式呼叫non-const成員函式是一種錯誤。因為物件有可能被改變。要使這樣的**通過編譯器,需要使用const_cast將*this身上的const性質釋放掉。non-const成員函式本來就可以對其物件做任何動作,故在其中呼叫乙個const成員函式不會帶來風險。

const是個奇妙非比尋常的東西。在指標和迭代器身上,在指標、迭代器及reference指涉的物件身上;在函式引數和返回型別身上;在local變數身上;在成員函式身上,林林總總不一而足。應該應可能使用它。

注意:1)將某些東西宣告為const可幫助編譯器偵測出錯誤用法。const可別施加於任何作用域內的物件、函式引數、函式返回型別。成員函式本體。

2)編譯器強制實施bitwise constness,但你編寫程式時應該使用「概念上的常量性」(conceptual constness)。

3)當const和non-const成員函式有著實質等價的實現時,令non-const版本呼叫const版本可避免**重複。

盡可能使用 const

使用 const 的好處在於它允許指定一種語意上的約束 某種物件不能被修改 編譯器具體來實施這種約束。通過 const,你可以通知編譯器和其他程式設計師某個值要保持不變。只要是這種情況,你就要明確地使用 const 因為這樣做就可以借助編譯器的幫助確保這種約束不被破壞。對指標來說,可以指定指標本身為...

盡可能使用const

一 中心思想 1 將某些東西宣告為const可幫助編譯器偵測出錯誤用法。const可被施加於任何作用域內的物件 函式引數 函式返回型別 函式返回型別 成員函式本體 2 編譯器強制實施bitwise constness,但你編寫程式時應該使用 概念上的常量性 3 當const和non const成員函...

盡可能使用const

編譯器可以對其進行靜態資料型別檢查 若你在編寫函式時,並沒有打算改變引數,這是就應該將引數的型別設定為const reference,這樣既可以保證引數的常量性,又提高了傳值的效率 若函式的返回值時const pointer,則返回值不可被直接修改,而且返回值必須賦值給const同種型別 令函式返回...