讀書筆記 Effective C

2022-03-01 14:50:31 字數 2831 閱讀 8966

const是常量的意思,它可以定義乙個不可改變的量,主要用於以下幾個地方:

舉個例子:

const

int var = 3;

此時var的值就不能改變了。也正是因為const的變數不能輕易修改儲存的值,所以在宣告的時候就要初始化,這樣就是不行的:

const

int var;

編譯器就會報錯。

指標是特殊的變數,有時我們希望對它所指向的物件操作,而有時我們又希望對指標本身進行操作。同樣,const應用於指標也有兩個含義:乙個是指向常量(指向的內容不可更改),乙個是常量指標(指標的指向不可更改)。看下面這兩個例子:

const

int* p = &a;/* p為指向常量的指標,即p指向的物件是常量,不可以通過*p = 3 來修改a的值,但這時p = &b換個指向還是可以的 */

int* const p = &a; /* p為常量指標,即p的指向不可更改,不可以通過p = &b來修改p的指向,但這時*p = 3改變a的值還是可以的 */

const

int* const p = &a; /* p為指向常量的常量指標,p的指向以及指向的物件都不可以更改,無論是*p = 3,還是p = &b都是錯誤的 */

還有一種形式是int const *p,這種形式是表示常量指標,還是指向常量的指標呢?effective c++給出的建議是看「*」的位置,當const位於星號左側時,const修飾的是值,即表示指向常量,而當const位於星號右側時,const修飾的是指標,即表示常量指標。所以int const *p等價於const int *p,你想對了嗎?(關鍵看const修飾的是*p還是p)。

const有時還會修飾函式的形參或者函式的返回值,都是屬於1或2這兩種情況。修飾函式形參的用法:

void fun(const

char a)

還有乙個地方要注意一下,若有:

void fun1(const

char* a)

void fun2(char *a)

當實參為const時,比如const char* msg = 「hello」,此時fun1(msg)是可以的,但fun2(msg)會報編譯錯,說是無法將const char*轉成char*;而當實參為普通變數時,比如char* msg = 「hello」,fun1(msg)和fun2(msg)都是ok的。這是為什麼呢?因為當const的變數傳遞給非const的變數會不安全(非const的變數可以修改原來定義為常量的東西了!),所以c++限制了這種用法(需用強制型別轉換來告訴編譯器,編譯器才會放行);而反過來,當非const的變數傳遞給const變數時,不存在安全問題,所以c++編譯器總是會放行的。因此,如果在函式體內確實不改變形參a的值,那麼採用帶const的fun1的寫法會更好,適用性更強。

c++的stl中使用迭代器作為介面,它定義了普通的迭代器,如vector::iterator,也定義了指向常量的迭代器,如vector::const_iterator,初學者可能想當然地認為const vector::iterator等價於vector::const_iterator,其實不是這樣的,const vector::iterator表示這個迭代器的指向不可以更改,即表示的是常量迭代器。

const放在類中成員函式的後面,表示這個成為函式不會修改類的成員變數,比如:

class a

;

注意這裡的fun1()函式後面有乙個const,表示這個函式不會修改類的成員變數(在它的函式體裡面出現任何改變a或b的值的操作,均不能通過編譯);另一方面fun2()函式後面沒有const,表示這個函式可能修改類的成員變數,注意這裡用的詞是「可能」,fun2()可以修改也可以不修改,但為了增強安全性,所以良好的程式設計風格一般會把不改動成員變數的成員函式修飾為const的。

有一點要切記:有無const是可以構成成員函式的過載的!

在本書中還提到了乙個尖銳的問題,如果假定類是這樣的:

class b

;

我們看到,類的成員函式是指標,假定它在建構函式時會被初始化,而指向一段記憶體空間。那麼如果不改變p本身(即指向不變),但是改變了p指向的內容(比如*p = 3),這樣到底算不算對成員變數進行改動了呢?

讀者可以在vs環境中寫一下測試用例,可以發現vs編譯器對這種情況是放行的,*p = 3完全可以通過,但是p = &b就不可以了。

雖然編譯器是放過你了,但這也許並不是你的本意,本書中推薦的是「從邏輯上看」,就要交由寫**的你去好好思量一下。如果在某個函式裡確實改動了p所指向的內容,那麼最好就不要加上const;反過來,如果加上了const就不要改變成員變數,包括它所指向的值。

我覺得這是乙個非常重要的內容,有沒有加const是構成函式過載的,但通常這種過載的相似度很高,就用書上的例子:

class testblock
char& operator(size_t position)
};

可以看到兩個過載函式裡面的操作都是一樣的,別因此認為可以用ctrl+c,ctrl+v而省事了,如果你要改動其中乙個函式體裡的內容,另乙個就要同步更新,而萬一你忘記了更新,後果是非常嚴重的!

乙個好的方法來實現同步——在非const的函式中呼叫const函式!這樣來修改:

char& operator (size_t position)

說白了,就進行兩次轉換,一次是把非const的物件(就是自己(*this)轉成const物件),但注意返回值要求是非const的,所以用const_cast再進行一次轉換就ok了。關於c++轉換可以參照本部落格的

《effective C 》讀書筆記

1,c 關鍵字explicit c 中,乙個引數的 建構函式 或者除了第乙個引數外其餘引數都有預設值的多參建構函式 承擔了兩個角色。1 是個 構造器,2 是個預設且隱含的型別轉換操作符 所以,有時候在我們寫下如 aaa 這樣的 且恰好 的型別正好是aaa單引數構造器的引數型別,這時候 編譯器就自動呼...

Effective C 讀書筆記

一 讓自己習慣c 1 條款01 視c 為聯邦語言 c 的組成可分為四部分 1.c c 仍然以c語言為基礎。區塊 語句 預處理 內建資料型別 陣列 指標等都來自c。2.object oriented c c with classes所訴說的 classes 包括構造和析構 封裝 繼承 多型 virtu...

讀書筆記 Effective C

部分條款過於深奧,部分條款已了然於心,僅記錄當下所識所學 對於常量巨集定義,最好用const代替 define 對於函式巨集定義,最好用inline代替 define include ifdef ifndef仍被需要 內建物件記得手動初始化 使用成員初始列替換賦值操作 以local static替換...