C++中常量的使用

1. C語言中的常量

我們都知道C語言中常量通常用const來修飾。

Tips:

很多資料把C語言里面的const叫常量,其實(shí)不太對(duì)。舉例如下:

#include <stdio.h>
int main()
{
? ? const int a = 10;
? ? int b[a] = {0};? // 錯(cuò),a是只讀量,不是常量,不能作為數(shù)組大小 ,無法通過編譯,如果用 #define a 10 就可以編譯
? ? int i = 0;
? ? for (i = 0; i < 10; i++) {
? ? ? ? printf("a[%d] = %d\n", i, b[i]);
? ? }
? ? return 0;
}

其實(shí),C語言里面,const很明確只有「只讀」一個(gè)語義,是不能修改的。

例如:

const int a = 10;
a = 20; // 錯(cuò),const修飾的變量是只讀的,不能修改

但是很多人不知道這個(gè)只讀量其實(shí)不太安全,因?yàn)榭梢酝ㄟ^取地址去修改它。例如:

const int a = 10;
int *p = &a;
*p = 20; // 對(duì),只讀量被間接修改了

Tips:

上面這種寫法不好,正常寫代碼不要這么干,編譯器也會(huì)告警,但確實(shí)可以執(zhí)行。
但是注意:字符串常量是無法通過地址間隔修改的,因?yàn)樽址A看嬖谖淖殖A繀^(qū)。


2. C++語言中的常量

C++兼容C,又有所擴(kuò)展。最開始的時(shí)候const不僅表示只讀(兼容C),還表示常量(擴(kuò)展),正是由于它有兩重含義,具有二義性,所以在C++11里面引入了constexpr來表示常量。如圖1所所示。


圖1 C語言中const表示只讀,C++中const表示只讀和常量

而且,C++中強(qiáng)化了的const的只讀含義,徹底不允許修改它,哪怕是通過指針間隔修改都不行,例如:

const_test2.cpp

#include <iostream>

using namespace std;

int main()
{
? ? const int a = 10;
? ? int *p = &a;
? ? *p =20;
? ? cout << "a = " << a << endl;
? ? return 0;
}

圖2 C++中修改const類型變量,編譯報(bào)錯(cuò)

Tips:

constexpr定義的常量在C++里面也是無法修改的,間隔通過指針也無法修改。


3. const與constexpr區(qū)別

C++里面const與constexpr的兩點(diǎn)區(qū)別:

(1)constexpr修飾的變量,只接受編譯期就已經(jīng)確定好的值或表達(dá)式。const修飾的變量既可以是編譯期的也可以是運(yùn)行期的:如果是編譯期能確定值得就是常量,如果是運(yùn)行期才能確定值得就是只讀量。
(2)constexpr只能修飾int、char等基本數(shù)據(jù)類型,不支持修飾string等類型。const常量可以修飾任何類型。

Tips:

上面提到,constexpr修飾不了string,也是有替代方案的,可以用string_view。string_view是C++17引入的,具體用法和string差不多。
class A {
public:
? ? static?constexpr string s = "aaa";? ? //?error
};

class A {
public:
? ? static constexpr string_view s = "aaa";? ?// ok,C++17支持
};


4. C++中常量定義位置

1、如果常量只在某一個(gè)函數(shù)內(nèi)部使用,可以在函數(shù)內(nèi)部定義常量。

2、如果常量只在某一個(gè)類的內(nèi)部使用(比如一個(gè)類的多個(gè)成員函數(shù)都用到),可以將它定義成類的成員變量(加 static const)。

(1)加const的原因不用多說
(2)加static是為了當(dāng)這個(gè)類有多個(gè)對(duì)象時(shí),共用一份static變量,減少內(nèi)存占用

這里有兩點(diǎn)要注意:

(1)C++里面規(guī)定:類的const成員,必須在類的初始化列表中進(jìn)行初始化,這一點(diǎn)在C++11之后就不對(duì)了,可以直接在類內(nèi)初始化。例如:

class A {
public:
? ? const int a = 0; // C++11之后const成員可以直接在類內(nèi)初始化
};

(2)C++里面規(guī)定:類的static成員,必須在類外進(jìn)行初始化,這一點(diǎn)在C++11之后仍然正確。例如:

class A {
public:
? ? static int a;
};

int A::a = 10;

那么,如果是成員變量既有const又有static修飾呢?

答案是,基本數(shù)據(jù)類型還是可以在類內(nèi)初始化,string類型必須在類外初始化,例如:

class A {
public:
? ? static const int a = 10;? ?// 基本數(shù)據(jù)類型,可以類內(nèi)初始化
? ? static const string s;? ? ? // string類型,必須在類外初始化
};

const string A::s = "aaa";

3、如果常量只在某個(gè)模塊中(該模塊有多個(gè)類)使用時(shí),可以考慮使用命名空間。

4、如果常量全局使用時(shí),則在公共頭文件中聲明。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容