"const T " VS "T const " VS const 作用匯總

聲明符:

這是第一個觀點:

CC++的每一個聲明都有兩個主要的部分:一串0個或多個聲明修飾符+一串0個或多個聲明符(多個申明符用逗號分開)例如:

   Static unsigned long int         *x[N];

Declarationg specifier )(declarator

聲明符就是要聲明的名字,經常與像*,[],()&((在C++)組合在一起。在聲明符中這個符號*意味着“指向”,[]意思是“數組”。因此,*x[N]是一個聲明符說明x是一個有N個指針元素組成的數組,類型是在類型修飾符中指定的類型。例如,

Static unsigned long int *x[N];

x聲明爲這種類型的對象:“N指向無符號長整型元素組成的數組。“

我怎麼知道*x[N]是一個指針數組而不是指向數組的指針呢?

它遵循這個原則:在聲明符組中操作符的優先級與他們在表達式中的一致。

例如:[]*的優先級高。因此,在這個聲明符中*x[N]意味着x 首先是一個數組,然後纔是它的元素是一個指針。


圓括號:();在聲明符中有兩個作用:

一是作爲函數調用操作符;

二是分組。


作爲函數調用操作符時,()與[]的優先級相同,分組時()擁有最高的優先級。

例如,*f(int)是一個聲明符,指定f是一個返回指針類型的函數。而(*f)(int)指定f是指向一個函數的函數指針。

聲明符可能包含不止一個標識符。這個聲明符*x[N]包含兩個標識符,xN

只有一個標識符是被聲明的,被稱爲聲明ID。其他的,如果還有的話,必須似乎在之前聲明的了。例如在這個聲明符中x是聲明ID


聲明限定符

一些聲明限定符可以是類型限定符諸如int,unsigned或者是一個新類型的標識符。他們也可以使存儲類限定符像extern或者static。在C++中他們也可以是函數限定符像inline或者virtual


下面是另一個觀點:

類型限定符作用於聲明符ID的類型,其他的限定符提供非類型信息,這些信息直接作用於聲明ID

例如:static unsigned long int *x[N]

聲明x爲一個變量類型:“由N個指向無符號長整型的指針組成的數組。“ ;關鍵字static限定x爲靜態分配的內存。


下面是另一個重要的觀點:

聲明限定符在聲明中的順序是無關緊要的。例如:

Const VP vectorTable[]

等價於

VP const vetorTable[]

const void* vetorTable[]

等價於

void const* vetorTable[]

我們大多數人將諸如static這樣的存儲類限定符(最左邊)作爲第一個聲明限定符,但是這只是一個慣例,不是語言本身的要求。

聲明限定符constvolatile是不同的:唯一的聲明限定符也能出現在聲明符中的是constvolatile

例如:在void*const vectorTable[]中的const出現在了聲明符中。

在這中情況下,你就不能重新組織關鍵字的順序,例如:*const void vetorTable[]是錯誤的。


 對於編譯器來說聲明限定符的順序是無關緊要的。於是這兩種聲明是等價的:

const void *vetorTable[]; 

void const *vectorTable[];

幾乎所有的CC++編程者都傾向於將constvolatile寫在類型限定符的左邊。我更喜歡將他們寫在右邊,並且我強烈推薦寫在後邊的這種寫法。

儘管一般CC++是從左到右, 從上到下讀的,讀指針聲明的時候,在某種意義上說,是相反的。也就是說,指針聲明是從右到左讀的。

通過將const置於其他類型限定符的右邊,你可以嚴格的從右到左讀指針聲明,並且將const出現在右邊的位置。

例如:

T const *p;

<------------

p聲明爲指向cons  T 的指針;

並且:

T *const p;

<------------

p聲明爲指向Tconst指針

const寫在其他聲明限定符之後實際上使得更加容易看到consttypedef結合的效果。

Typedef void*  VP;

Const VP  vectorTable[];

一種轉化是象下面這樣置換VP

Const (VP )vectorTable[]

Const(void*)vetorTable[]

使得它看起來vectorTable具有這種類型“指向const  void 的指針數組“,這是錯誤的

正確的轉換是將VP置換爲:

const  (VP) vectorTable[]

(void *)const vectorTable[]

也就是說,vectorTablel是指向voidconst指針數組,但是它卻不是顯然的。

const寫在聲明限定符的最右邊使得更容易看到正確的翻譯,

(VP) const vectorTable[];

(void *)const vectorTable[];

現在我意識到我正在推薦一種其他人很少用的風格,其他人都會將const放在左邊;

但是,鑑於很少有CC++的程序員知道在聲明中使用const時自己在做什麼,每個人都不這樣做是支持現在流行風格。爲什麼不抵制這種趨勢。嘗試着使用一種更加清晰的風格呢?

只要我還從事着這個職業,我就會一如既往的支持這種風格。儘管這對大多數程序員還沒有任何影響,但是很多人還是養成了書寫的壞習慣。

Const int  *p;(更加規範化)

而不是

Constint*  p;

也就是說,他們將空格和*作爲聲明限定符而不是聲明符,我真的相信程序員這樣書寫給他們自己和其他人造成麻煩。

當然,空格對編譯器毫無影響,但是將空格置於*之後會給人關於聲明的內在結構造成一種錯誤的印象。


---------------------------------------------------------------------------------------------------------

const的作用 

const是C語言的一種關鍵字,起受保護,防止以外的變動的作用!可以修飾變量,參數,返回值, 函數體。

const可以提高程序的健壯性,你只管用到你想用的任何地方。


(一)const修飾參數。const只能修飾輸入參數。
1、如果輸入參數是指針型的,用const修飾可以防止指針被意外修改。
2、如果參數採用值傳遞的方式,無需const,因爲函數自動產生臨時變量複製該參數。

3、非內部數據類型的參數,需要臨時對象複製參數,而臨時對象的構造,析構,複製較爲費時,因此建議採用前加const的引用方式傳遞非內部數據類型。而內部數據類型無需引用傳遞。


(二)const修飾函數返回值
1、函數返回const指針,表示該指針不能被改動,只能把該指針賦給const修飾的同類型指針變量。
2、函數返回值爲值傳遞,函數會把返回值賦給外部臨時變量,用const無意義!不管是內部還是非內部數據類型。

3、函數採用引用方式返回的場合不多,只出現在類的賦值函數中,目的是爲了實現鏈式表達。


(三)const修飾C++成員函數。任何不修改數據成員的函數都應該聲明爲const類型,如果const成員函數修改了數據成員或者調用了其他函數修改數據成員,編譯器都將報錯!
class stack
{
	public:
		int GetCount(void) const ;
	private:
		int m_num;
};

int stack::GetCount(void) const
{
	m_num++;
}

編譯器輸出錯誤信息:error C2166: l-value specifies const object。


(四)const 修飾變量,表示該變量不能被修改。
1、const char *p 表示 指向的內容不能改變
2、char * const p,就是將P聲明爲常指針,它的地址不能改變,是固定的,但是它的內容可以改變。
3、這種const指針是前兩種的結合,使得指向的內容和地址都不能發生變化.
const double pi = 3.14159;

const double *const pi_ptr = &pi;


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章