C++中const關鍵字修飾
C++中const使用的地方非常多,修飾包括:全域性變數、函式、函式引數等等,這篇文章主要是總結一下const各種使用的規則以及需要注意事項。
const名叫常量限定符,用來限定特定變數,以通知編譯器該變數是不可修改的。習慣性的使用const,可以避免在函式中對某些不應修改的變數造成可能的改動。
C++中const的主要用法大致上可以分為以下幾類:
- 修飾基本資料型別
- 應用到函式中
- 在類中用法
- const修飾類物件,定義常量物件
1.const修飾基本資料型別
主要是修飾值變數、reference、pointer
1.1修飾一般常量或則陣列
比如:
const int a = 10;
const int arr[3]={1,2,3};
對於類似這些基本資料型別,修飾符const可以用在型別說明符前,也可以用在型別說明符後,其結果是一樣的。在使用這些常量的時候,只要不改變這些常量的值便好。
1.2const修飾指標變數*及引用變數&
const修飾指標(*)
這裡有一些實際的示例:
int x= 100;
const int* a1 = &x;//[1]
int const * a2 = &x;//[2]
int* const a3 = &x;//[3]
const int* const a = &x;//[4]
《Effective c++》Item21上的總結非常直觀明瞭。
- 如果const位於星號*的左側,則const就是用來修飾指標所指向的變數,即指標指向為常量;
- 如果const位於星號*的右側,const就是修飾指標本身,即指標本身是常量。
根據這條規律,[1]和[2]兩條中,const位於星號的左側,所以const含義是修飾變數a1和a2指標指向的內容是常量,也就是不能做 *a1 = 1或則 *a12 = 1這種類似操作,編譯器會報錯。
[3]為指標本身是常量,而指標所指向的內容不是常量,這種情況下不能對指標本身進行更改操作,如a++是錯誤的.
[4]為指標本身和指向的內容均為常量。
const修飾reference(&)
同樣給出一些示例:
int x =100;
int const &a=x;//[1]
const int &a=x;//[2]
int &const a=x;//[3]這種方式定義是C、C++編譯器未定義,雖然不會報錯,但是該句效果和int &a一樣。
對於[1]和[2]這兩種定義方式是等價的,此時的引用a的值不能被更新。如:a++ 或則給a賦值這是錯誤的。
2.const應用到函式中
const在函式中的應用主要有三點:
- 作為引數的const修飾符;
- 作為函式返回值的const修飾符
- 作為函式的const修飾符
不管是作為函式引數的const修飾符還是返回值的修飾符,其實際含義都是一樣的。
const修飾函式引數
比如:void fun0(const A* a ); 或則 void fun1(const A& a);
呼叫函式的時候用相應的變數初始化const常量,則在函式體中,按照const修飾的部分進行常量化。
比如const A* a 則不能對傳遞進來的指標指向的內容修改,保護原指標所指向的內容;
比如const A& a則不能對傳遞進來的引用物件的內容修改,保護原引用物件所的內容。
注意:引數const通常用於引數為指標或引用的情況。
const修飾函式返回值
修飾返回值的const,如const A fun2( ); const A* fun3( );
這樣聲明瞭返回值後,const按照"修飾原則"進行修飾,保護函式返回的指標指向的內容或則引用的物件不被修改。
const修飾函式
const作用於函式還有一種情況是,在函式定義的最後面加上const修飾,比如:
A fun4() const;
其意義上是不能修改除了函式區域性變數以外的所在類的任何變數。
3. 類中定義常量(const特殊用法)
我們要想在類中實現常量定義大致上有幾種實現方式
1.使用列舉型別
class test
{
enum {SIZE1=10, SIZE2=20};//列舉常量
int array1[SIZE1];
int array2[SIZE2];
}
2.使用const
不能在類宣告中完成初始化const資料成員。 以下用法編譯器會報錯,因為類物件未被建立時,編譯器不知道SIZE的值是什麼。
// 錯誤例項
class test
{
const int SIZE = 100;//編譯器報錯,企圖在類宣告中初始化const資料成員
int array[SIZE];//錯誤,未知SIZE
}
正確使用const用法是:const資料成員的初始化只能在類建構函式的初始化表中進行。
class A
{
A(int size);//建構函式
const int SIZE;
};
A::A(int size) : SIZE(size) // 建構函式的初始化表
{
}
//error 賦值的方式是不行的
A::A(int size)
{
SIZE=size;
}
void main()
{
A a(100); // 物件 a 的SIZE值為100
A b(200); // 物件 b 的SIZE值為200
}
注意:對const成員變數的初始化,不能在變數宣告的地方,必須在類的建構函式的初始化列表中完成,即使是在建構函式內部賦值也是不行的。
3.使用static const
通過結合靜態變數來實現:
class Year
{
private:
int y;
public:
static int const Inity;
public:
Year()
{
y=Inity;
}
};
int const Year::Inity=1997;//靜態變數的賦值方法,注意必須放在類外定義
void main()
{
cout<<Year.Inity<<endl;//注意呼叫方式,這裡是用類名呼叫的。
}
到這裡就把在類中定義常量的方法都陳列出來了。
4.const定義常量物件,以及常量物件的用法
對於不管是標準庫中的物件或則是我們自定義的物件,如果我們定義的是const物件,那麼對於const物件只能呼叫const修飾的函式,其餘的函式都不能呼叫。
如下例子:
class test
{
public:
test():x(1)
{
y=2;
}
~test()
{}
void set(int yy)
{
y=yy;
}
int getx() const
{
return x;
}
const int x;
int y;
};
void main()
{
const test t;// 定義的一個const物件
t.set(33);//error,set方法不是const修飾的方法,編譯器會報錯。
t.getx();
}