關於C++中const的一些研究

       最近複習的過程中發現網上對於const的說法不一,讓人摸不着頭腦,爲了搞清其原理,決定通過反彙編的方式來看一看其內部究竟發生了什麼,下面是一篇簡單的介紹反彙編指令的文章,用來理解本次所研究的東西已經足夠

https://www.lagou.com/lgeduarticle/1754.html

下面將按照一個觀點一個例子的方式來進行:(該測試基於VS2017環境)

1.將字面值賦給const變量時,會在編譯期間將程序中用到該變量的地方替換成對應的數值(類似於宏替換),同時該變量在內存中分配空間,通過指針也可以對該變量的內容進行更改,但不會影響到程序中使用const變量的地方,因爲程序真正執行的時候,const變量所在的地方已經替換成了字面值,例如

#include<iostream>

int main()

{

    const int x = 12;

    int *ppx = (int *)&x;

    *ppx = 13;

    int b = *ppx;

    int c = x;

    std::cout << "*ppx = " << *ppx << " x = " << x << std::endl;

    std::cout << "b = " << b << " c = " << c << std::endl;

    system("pause");

}

 

其反彙編的結果爲:

從結果分析可知,

在1處,程序將字面值0Ch直接賦值給了x變量

在2處,程序通過指針訪問x變量的地址,將0Dh賦值給了x所在的內存位置

其過程可由下圖看出

執行前:

執行後:

在3處,程序通過訪問x變量所在的內存地址將值取出並賦給變量b

在4處,本應將x變量的值賦給變量c,但在反彙編結果中可見,程序將字面值0Ch直接賦給了變量c,而沒有通過地址取值

 

2.若通過一個變量賦值給一個const變量,那麼上面的說法將不再成立,經過試驗發現,此種情況下const限制只對變量名訪問有效,對於指針修改的方式並不能起到限制寫的作用,試驗過程如下:

#include<iostream>

//此代碼相對於上一個例子只是將x變量賦值的方式改變,其餘位置不變

int main()

{

    int y = 12;

    const int x = y;

    int *ppx = (int *)&x;

    *ppx = 13;

    int b = *ppx;

    int c = x;

    std::cout << "*ppx = " << *ppx << " x = " << x << std::endl;

    std::cout << "b = " << b << " c = " << c << std::endl;

    system("pause");

}

其反彙編的結果爲:

此次反彙編結果僅1,2兩處與先前不同,中間部分一致,不再贅述

從結果分析可知:

通過變量賦值方式初始化的const變量,其賦值時需要訪問原變量的地址

通過此方式初始化的const變量,在使用時也會到內存中取它的值,而不會像上一個例子中一樣做宏替換

 

3.代碼中出現字符串的地方都會在內存常量區中保存,若同一個字符串在代碼中多次出現,編譯器會自動識別,不會重複產生同樣的串

#include<iostream>

#include<string>

int main()

{

    std::string *s = new std::string("aaa");

    const char *cptr = "aaa";

    char * cptr1 = (char *)"bbb";

    char ch[] = "aaa";

   

    system("pause");

}

其反彙編的結果爲:

       觀察1.2.4可看出,當程序中使用同一個字符串時,編譯器並不會產生新的串,而是共用一塊地址中的內容,當串不同時,纔會在常量區中保存新的串

       觀察2.3並結合圖二可看出,當使用指針指向常量區中的地址時,由於常量區的內容本身就是不可更改的,因此,用不用const都是一樣的,即使強制類型轉換爲普通指針修改了其中的內容,也會在運行時產生異常

       觀察2.4可看出,使用指針指向常量時,指針變量內存入的是常量區中常量的地址值,而使用字符數組保存字符串時,編譯器會將常量區中的常量複製一份賦給棧中的字符數組空間

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章