1. 程式人生 > >深入理解C++中的Const,Mutable以及Volatile

深入理解C++中的Const,Mutable以及Volatile

private 結果 返回 成員變量 一個 del oid 深入 lock

我一直認為const表示一個常量,常量就是一個無法被修改的值,但是沒有深入理解const的實現,甚至不知道mutable和volatile的存在,最近在書中看到了這一部分的知識,所以本文將詳細解析這幾個關鍵詞。

首先考慮以下幾個問題:

1. const int a和int const a的區別。

2. const char* s和char *const s的區別。

3. 下列代碼有問題嗎?如果有問題應該如何修改?

class A
{
private:
    int a;
    const int fun()
    {
        a = 1;
    }
    int fun() const
{ a = 2; } };

4. 下列代碼一定能達到目的嗎?為什麽?

//延時函數
void delayFun(unsigned int a)
{
    while (a--)
    {

    }
}

5.下列代碼運行結果是什麽?

const int i = 1;
int* j = (int*)(&i);
*j = 2;
printf("%08x %d %08x %d", &i, i, j, *j);

針對上述問題解答:

1. 無區別,表示a是一個const int變量,a無法被修改,並且a可能編譯器優化掉(無內存地址)。

2. const char* s表示s是一個常量字符串的指針,它可以指向不同的常量字符串,例如

const char* s1 = "abc";
s1 = "xyz";
但是字符串內容無法被修改,下列代碼出錯:
s1[0]=c;

char* const s表示一個字符串指針的常量。指向一個唯一的字符串指針,無法後續修改,下列代碼出錯:

char* const s1 = "abc";
s1 = "xyz";

3. const int fun() 表示一個函數返回值是const int(事實上const int是無意義的),此函數和普通函數沒區別。int fun() const表示該函數是常量函數,此函數無法修改類中的成員變量(規定),如果一定要修改類中的成員變量,可以將該成員變量定義為mutable,如下:

class A
{
private:
    mutable int a;
    const int fun()
    {
        a = 1;
    }
    int fun() const
    {
        a = 2;
    }
};

4. 代碼可能會被優化掉,此函數是一個無效的循環,這類代碼會被編譯器優化掉,優化後就不存在延時效果了。如果一定要達到延時效果,可以將a定義為volatile。volatile表示此變量可能因為各種原因被修改,告訴編譯器不要優化此變量產生的代碼(這個一般是底層可能用到,硬件之類的,如果不理解volatile,可能導致代碼出現預料之外的情況)。

5. 這段代碼如果是debug模式下可能會被編譯器提示出錯,因為這裏采用了一個強制轉換修改了一個常量的值(編譯器的理解是,常量是無論如何都無法被修改的,所以高級一點的編譯器可能會對此代碼報錯),但是這段代碼從C語言的語言層面上來說是沒問題的,C語言裏可以將任意指針轉換為需要的指針。這段代碼在C++中輸出:

0075f8b4 1 0075f8b4 2

輸出地址是一樣的,但是值不一樣。

為什麽會這樣呢?按理說地址一樣,他的值肯定也是一樣的,原因還是在與編譯器的優化(不是編譯器的錯,const就是一個常量,他就應該是無法被修改的,既然無法被修改,用常量替換沒問題)。編譯器將所有使用i的地方會用他的值替換,類似與C語言中的#define。這裏使用了強制轉換強制修改i所在內存的值,但是這個值變化了,不會修改編譯器優化後的代碼(優化後的代碼和和i這個符號都無關了),所以有上述輸出。如何修改呢?使用volatile,volatile會要求編譯器不要優化該常量,既然不會優化,那麽使用i的地方會使用i這個符號而不會優化為常量的值了。如下:

const volatile int i = 1;
int* j = (int*)(&i);
*j = 2;
printf("%08x %d %08x %d", &i, i, j, *j);

可以這麽理解,const是一個C++為了替換C語言define而產生的關鍵字,const會留下一些坑。所以就使用mutable和volatile來填補這些坑。如果沒搞清const的這些問題,以後在開發過程中可能會碰到坑。

深入理解C++中的Const,Mutable以及Volatile