C++作為一種面向對象的經典語言,它是非常的強大,它的每個部分都值得我們去深入了解。
const的基本概念:
const名叫常量限定符,用來限定特定變量,以通知編譯器該變量是不可修改的。習慣性的使用const,可以避免在函數中對某些不應修改的變量造成可能的改動。
下面我就const的用法來談談:
const的用法大緻可分為以下幾個方面:
(1)const修飾基本資料類型
(2)const應用到函數中
(3)const在類中的用法
(4)const修飾類對象,定義常量對象
一、const修飾基本資料類型
1.const修飾一般常量及數組
const int a=10; 等價的書寫方式: int const a=10;
const int arr[3]={1,2,3}; int const arr[3]={1,2,3};
對于類似這些基本資料類型,修飾符const可以用在類型說明符前,也可以用在類型說明符後,其結果是一樣的。在使用這些常量的時候,隻要不改變這些常量的值便好。
2.const修飾指針變量*及引用變量&
介紹本部分内容之前,先說說指針和引用的一些基本知識。
指針(pointer)是用來指向實際記憶體位址的變量,一般來說,指針是整型,而且一般的大家會接受十六進制的輸出格式。
引用(reference)是其相應變量的别名,用于向函數提供直接通路參數(而不是參數的副本)的途徑,與指針相比,引用是一種受限制的指針類型,或者說是指針的一個子集,而從其功能上來看,似乎可以說引用是指針功能的一種高層實作。
關于運算符&和*:
在C++裡,沿襲C中的文法,有兩個一進制運算符用于指針操作:&和*。按照本來的定義,&應當是取址符,*是指針符,也就是說, &用于傳回變量的實際位址,*用于傳回位址所指向的變量,他們應當互為逆運算。實際的情況也是如此。
在定義變量的引用的時候,&隻是個定義引用的标志,不代表取位址。
舉例:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLlR2bjlHcvN2LcNXZnFWbp9CXt92YuM3ZvxmYuNmLu9Wbt92Yvw1LcpDc0RHaiojIsJye.gif)
1 #include<iostream.h>
2 void main()
3 {
4 int a; //a is an integer
5 int *aPtr; //aPtr is a pointer to an integer
6
7 a=7;
8 aPtr = &a;
9 cout<<"Showing that * and & are inverses of "<<"each other.\n";
10 cout<<"a="<<a<<" *aPtr="<<*aPtr<<"\n";
11 cout<<"&*aPtr = "<<&*aPtr<<endl;
12 cout<<"*&aPtr = "<<*&aPtr <<endl;
13 }
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLlR2bjlHcvN2LcNXZnFWbp9CXt92YuM3ZvxmYuNmLu9Wbt92Yvw1LcpDc0RHaiojIsJye.gif)
運作結果:
了解完指針和應用的基本概念之後,下面繼續我們的話題。
const修飾指針(*):
const int* a = & [1] //非常量資料的常量指針 指針常量
int const *a = & [2] //非常量資料的常量指針 a is a pointer to the constant char variable
int* const a = & [3] //常量資料的非常量指針指針常量 常量指針 a is a constant pointer to the (non-constant) char variable
const int* const a = & [4] //常量資料的常量指針
可以參考《Effective c++》Item21上的做法,
如果const位于星号*的左側,則const就是用來修飾指針所指向的變量,即指針指向為常量;
如果const位于星号的右側,const就是修飾指針本身,即指針本身是常量。
是以,[1]和[2]的情況相同,都是指針所指向的内容為常量,這種情況下不允許對内容進行更改操作,如不能*a = 3 ;
[3]為指針本身是常量,而指針所指向的内容不是常量,這種情況下不能對指針本身進行更改操作,如a++是錯誤的;
[4]為指針本身和指向的内容均為常量。
const修飾引用(&):
int const &a=x;
const int &a=x; int &const a=x;//這種方式定義是C、C++編譯器未定義,雖然不會報錯,但是該句效果和int &a一樣。 這兩種定義方式是等價的,此時的引用a不能被更新。如:a++ 這是錯誤的。
二、const應用到函數中
1.作為參數的const修飾符
2.作為函數傳回值的const修飾符
其實,不論是參數還是傳回值,道理都是一樣的,參數傳入時候和函數傳回的時候,初始化const變量
1 修飾參數的const,如 void fun0(const A* a ); void fun1(const A& a);
調用函數的時候,用相應的變量初始化const常量,則在函數體中,按照const所修飾的部分進行常量化,如形參為const A* a,
則不能對傳遞進來的指針的内容 進行改變,保護了原指針所指向的内容;如形參為const A& a,則不能對傳遞進來的引用對象進行改變,
保護了原對象的屬性。
[注意]:參數const通常用于參數為指針或引用的情況;
2 修飾傳回值的const,如const A fun2( ); const A* fun3( );
這樣聲明了傳回值後,const按照"修飾原則"進行修飾,起到相應的保護作用。
const Rational operator*(const Rational& lhs, const Rational& rhs)
{
return Rational(lhs.numerator() * rhs.numerator(),
lhs.denominator() * rhs.denominator());
}
傳回值用const修飾可以防止允許這樣的操作發生:
Rational a,b;
Radional c;
(a*b) = c;
一般用const修飾傳回值為對象本身(非引用和指針)的情況多用于二目操作符重載函數并産生新對象的時候。
類中的成員函數:A fun4()const; 其意義上是不能修改所在類的的任何變量。
三、類中定義常量(const的特殊用法)
在類中實作常量的定義大緻有這麼幾種方式實作:
1.使用枚舉類型
class test
{
enum { SIZE1 = 10, SIZE2 = 20}; // 枚舉常量
int array1[SIZE1];
int array2[SIZE2];
};
2.使用const 或static
C++11僅不允許在類聲明中初始化static非const類型的資料成員。
// using c++11 standard
class CTest11
{
public:
static const int a = 3; // Ok in C++11
static int b = 4; // Error
const int c = 5; // Ok in C++11
int d = 6; // Ok in C++11
public:
CTest11() :c(0) { } // Ok in C++11
};
int main()
{
CTest11 testObj;
cout << testObj.a << testObj.b << testObj.c << testObj.d << endl;
return 0;
}
到這裡就把在類中定義常量的方法都陳列出來了。
關于C++11新特性: C++11僅不允許在類聲明中初始化static非const類型的資料成員
總結如下:
- 對于static const 類型的成員變量不管是舊的C++标準還是C++11都是支援在定義時初始化的。
- 對于static 非const類型的成員變量C++03和C++11的标準都是不支援在定義時初始化的。
- 對于const 非static類型的成員變量C++03要求必須在構造函數的初始化清單中來初始化,而C++11的标準支援這種寫法,同時允許在定義時進行初始化操作。
- 對于非static 非const成員變量,C++03标準不允許在成員變量定義時初始化,但是C++11标準允許在類的定義時對這些非靜态變量進行初始化。
- 對于static非const成員變量的初始化方式并未改變,就是在相應的cpp檔案中寫成
即可,注意要在類定義之後。int CTest11::b = 5
四、const定義常量對象,以及常量對象的用法
class test
{
public:
test():x(1)
{
y=2;
}
~test()
{}
void set(int yy)
{
y=yy;
}
int getx() const
{
return x;
}
//protected:
const int x;
int y;
};
void main()
{
const test t;
t.set(33);//error
t.getx();
}
常量對象隻能調用常量函數,别的成員函數都不能調用。
五、使用const的一些建議
<1>要大膽的使用const,這将給你帶來無盡的益處,但前提是你必須搞清楚原委;
<2> 要避免最一般的指派操作錯誤,如将const變量指派,具體可見思考題;
<3> 在參數中使用const應該使用引用或指針,而不是一般的對象執行個體,原因同上;
<4> const在成員函數中的三種用法(參數、傳回值、函數)要很好的使用;
<5>不要輕易的将函數的傳回值類型定為const;
<6>除了重載操作符外一般不要将傳回值類型定為對某個對象的const引用;