《认清C++语言》---谈谈const
const類型修飾符可以:
1)? 用來說明符號常量和常數組(必須同時進行初始化,以后不能再更新)
C++中,用關鍵字const修飾的標識符稱為符號常量,或稱為const變量。
常量在使用前必須先定義同時初始化 ,例如:
const double pi = 3.1415926或
double const pi = 3.1415926;
?
通常情況下const同預處理器#define一樣只是將所賦值存入編譯器的符號表中(符號表僅僅在編譯時存在,在編譯過程中編譯器將程序中的名字與它在符號表中對應的數值作簡單的替換),在使用時進行值替換,并不為const創建存儲空間。
C++中const默認為內部連接(C中const默認是外部連接),也就是說const僅能被它所定義過的文件訪問,除非用extern聲明:extern const int a;這表示const的定義在其他的什么地方,這里僅僅是一個聲明,但是這樣的做法使const使用了外部連接,也就是說上面的extern強制進行了對const的存儲空間的分配。
(補充說明一個內部連接和外部連接。內部連接意味著只對正在編譯的文件創建存儲空間,別的文件可以使用相同的標示符的全局變量,編譯器不會發現沖突;外部連接意味著為所有被編譯過的文件創建一片單獨的存儲空間,一般全局變量和函數名的外部連接通過extern聲明,可以通過其他文件訪問)
如果強制取const常量的地址,或者用extern來聲明外部的const變量,C++編譯器就要為const變量分配存儲空間了。
由于用const修飾的變量的值不能被改變,只能被讀取,因此,在聲明處必須初始化變量,除非這個變量是用extern修飾的外部變量,例如:
const int d;??????????????? //err.
extern const int d;? //ok.此處只是聲明d變量,該變量是在其他文件中定義的
?
常數組:int const c[10] = {1,2,3,4,5,6,7,8,9,10};
因為在類對象里進行存儲空間分配時,編譯器不能知道const的內容是什么,所以不能把const常量作為編譯期間的常量,例如:
ACEClass AC
{
?????????? const size = 100;???????????? //非法
?????????? int array[size];????????????????? //非法
};
?
在類里const常量的意思是“在這個特定對象的生命期內,而不是對于整個類來說,這個值是不變的”。所以,要建立一個可以用在常數表達式中的類常量時,我們使用一個不帶實例的無標記的enum,例如:
ACEClass AC
{
?????????? enum {size = 100};
?????????? int en[size];
};
使用enum是不會占用對象中的存儲空間的,枚舉常量在編譯時被全部求值。
?
2) 用于說明常量對象(定義時同樣必須進行初始化,以后不能再更新)
定義格式如下:<類名> const <對象名>或const <類名><對象名>,如:
ACEPoint const ap(12, 200);
?
對于一個常量對象來說,只能調用常量成員函數(因為如果可以調用普通成員函數的話,就很可能通過普通成員函數改變對象的數據成員)。對于上面這個常量對象來說,如果改變它的數據成員或者調用它的一個非常量成員函數,編譯器都會給出出錯信息。
const對象只能調用const成員函數,一個普通對象同樣可以調用const成員函數,因此const成員函數更具一般性(能同時被const和非const對象調用撒), 因此,一般對于不修改數據成員的函數來說,應當將其聲明為常量成員函數,這樣就可以被常量對象所調用了。
使用常對象可以實現對數據共享的保護,同時常成員函數又打開了1個常對象的對外的接口,使保護和開放統一了起來。
?
3) 用于說明常量成員函數和常數據成員
常成員函數:使用const進行說明的成員函數。
常成員函數說明格式如下:<類型說明符> <函數名>(<參數表>) const;其中const是加在函數說明后面的類型說明符,它是函數類型的一個組成部分,因此在函數實現部分也要帶上const關鍵字。
?
常成員函數不能更新對象的數據成員,也不能調用該類中非const成員函數。
類的成員函數的原型后加上const是為了防止修改對象的數據成員的值,如:
class ACEClass
{
public: void setNum(int nu) const;
private: int num;
};
此時,常量成員函數setNum()的函數體中不能修改num的值,如:
void ACEClass::setNum(int nu)
{
???????? num = nu;????? //err.不能修改成員num的值
}
?
但是,有時我們在運用const成員函數是,遇到有需要改變的數據成員,這時可以用mutable來對該數據成員進行特別的指定:
class ACEClass
{
public: void setNum(int nu) const;
private: mutable int num;
};
void ACEClass::setNum(int nu) {num = nu};?? //ok.
?
常數據成員:因為const類型對象必須被初始化,并且不能更新,因此,在類中說明const數據成員后,在構造函數中只能通過成員初始化列表的方式來對數據成員進行初始化(理由是常量數據成員構造函數調用之前就必須有確定的數值,否則可以在構造函數中對其進行賦值或修改,這與常量數據不可修改相悖)。
?
在類的私有(Private)數據成員前加上const,則該私有數據成員就稱為常量數據成員。
注意:1)定義一個類就是定義了一種數據類型,而不是定義了某個對象,在類中定義數據成員時不能直接初始化,例如:
class ACEClass
{
private:
?????????? const int size = 10;???????? //err.
......
};
?
2)類中常量數據成員的初始化只能采用成員初始化列表的形式來初始化其數值,而不能采取賦值的方法,如下定義是錯誤的:
class ACEClass
{
private:
?????????? const int size;
public:
?????????? ACEClass() {size = 10;}?????????? //err.
};
?
正確的初始化代碼如下:
Class ACEClass? //增加了一個靜態的常數據成員和一個常引用
{
private:
?????????? const int size;??? //常數據成員
?????????? static const int height;? //靜態常數據成員
public :
?????????? const int &ref;????????????????? //常引用
};
const int ACEClass::height = 20;? //靜態常量數據成員在類外初始化
ACEClass::ACEClass() : size(10), ref(size){}
?
4) 用于說明常指針和常引用
常指針:
1)指向常量的指針:(意味著指向的元素是不能被改變的,定義格式:const Type *x;)
char str[] = “艾斯”;
const char *ptr = str;?? //以后*ptr不可改變,但ptr可以指向別的內存地址
定義指向常量的指針只限制指針的間接訪問操作,而不限制指針的直接訪問操作。
2)常量指針:(定義格式:Type* const x;)
char str[] = “艾斯”;
char* const ptr = str;? //以后ptr不可改變,但*ptr可以指向別的內存地址
????????
常引用:
使用const修飾符說明的引用稱為常引用,被引用的對象不能被更新,定義格式如下:
Const <類型說明符> &<引用名>,例如:const double &x;
?
在實際應用中,常指針和常引用往往用作函數的“形參”,這樣的參數稱為常參數。使用常參數表明該函數不會更新某個參數所指向的或引用的對象,這樣,在參數傳遞過程中就不需要執行拷貝初始化構造函數了。
?
5)用于說明按值傳遞的函數返回值
1)對于內部數據類型(int,float...)來說,函數按值返回的是否是一個const是無關緊要的,因為編譯器始終不會讓它成為一個左值。也就是說,此時用const來限定是多余的,如:
const int ace() {return 10;}????????????? //多余滴
void main() {int a = ace();}
?
2)但是對于用戶自定義類型來說,按值返回常量就很有意義了。這時函數返回值不能被修改或直接賦值;只有非const返回值才能作為一個左值使用,但這往往是沒有意義的,因為函數返回值在使用時通常保存為一個臨時量,該臨時量被作為左值使用并修改后,編譯器會在函數返回時將臨時量清除,這樣就丟失了所有的修改。
因此,一般函數返回值都是作為一個指針或引用來實現的。
????????
雖然const修飾的符號生存期間保持不變,但有時我們仍然想改變數據時,可以進行強制類型轉換,這里的轉換可以用傳統的C下的方式,在C++中,推薦用const_cast,然后就可以對其進行修改了。
?
?
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的《认清C++语言》---谈谈const的全部內容,希望文章能夠幫你解決所遇到的問題。