C++內存分區模型 內存分區模型

內存分區模型

C++程序在執行時,將程序大方向劃分爲4個區域

  • 代碼區:存放函數體的二進制代碼,由操作系統進行管理的。
  • 全局區:存放全局變量和靜態變量以及常量。
  • 棧區:由編譯器自動分配釋放,存放函數的參數值,局部變量等。
  • 堆區:由程序員分配和釋放,若程序員不釋放,程序結束時由操作系統回收。

意義:不同區域存放的數據,賦予不同的生命週期,給我們更大的靈活編程

1.1 程序運行前

​在程序編譯後,生成了exe可執行程序,未執行該程序前分爲兩個區域
代碼區:
​ 存放 CPU 執行的機器指令
​ 代碼區是共享的,共享的目的是對於頻繁被執行的程序,只需要在內存中有一份代碼即可
​ 代碼區是隻讀的,使其只讀的原因是防止程序意外地修改了它的指令
全局區:
​ 全局變量和靜態變量存放在此.
​ 全局區還包含了常量區, 字符串常量和其他常量也存放在此.
​ 該區域的數據在程序結束後由操作系統釋放.

//全局變量
int g_a = 10;
int g_b = 10;
 
//全局常量
const int c_g_a = 10;
const int c_g_b = 10;
 
int main() {
 
    //局部變量
    int a = 10;
    int b = 10;
 
    //打印地址
    cout << "局部變量a地址爲: " << (int)&a << endl;
    cout << "局部變量b地址爲: " << (int)&b << endl;
    cout << "全局變量g_a地址爲: " <<  (int)&g_a << endl;
    cout << "全局變量g_b地址爲: " <<  (int)&g_b << endl;
    //靜態變量
    static int s_a = 10;
    static int s_b = 10;
    cout << "靜態變量s_a地址爲: " << (int)&s_a << endl;
    cout << "靜態變量s_b地址爲: " << (int)&s_b << endl;
    cout << "字符串常量地址爲: " << (int)&"hello world" << endl;
    cout << "字符串常量地址爲: " << (int)&"hello world1" << endl;
    cout << "全局常量c_g_a地址爲: " << (int)&c_g_a << endl;
    cout << "全局常量c_g_b地址爲: " << (int)&c_g_b << endl;
    const int c_l_a = 10;
    const int c_l_b = 10;
    cout << "局部常量c_l_a地址爲: " << (int)&c_l_a << endl;
    cout << "局部常量c_l_b地址爲: " << (int)&c_l_b << endl;
    system("pause");
    return 0;
}

打印結果:


總結:

  • C++中在程序運行前分爲全局區和代碼區
  • 代碼區特點是共享和只讀
  • 全局區中存放全局變量、靜態變量、常量
  • 常量區中存放 const修飾的全局常量 和 字符串常量

1.2 程序運行後

棧區:
​ 由編譯器自動分配釋放, 存放函數的參數值,局部變量等
​ 注意事項:不要返回局部變量的地址,棧區開闢的數據由編譯器自動釋放

int * func()
{
    int a = 10;
    return &a;
}
int main() {
    int *p = func();
    cout << *p << endl;
    cout << *p << endl;
    system("pause");
    return 0;
}

堆區:
​ 由程序員分配釋放,若程序員不釋放,程序結束時由操作系統回收
​ 在C++中主要利用new在堆區開闢內存

int* func()
{
    int* a = new int(10);
    return a;
}
 
int main() {
 
    int *p = func();

    cout << *p << endl;
    cout << *p << endl;
    
    system("pause");
    return 0;
}

總結:
堆區數據由程序員管理開闢和釋放
堆區數據利用new關鍵字進行開闢內存

1.3 new操作符

​ C++中利用new操作符在堆區開闢數據
​ 堆區開闢的數據,由程序員手動開闢,手動釋放,釋放利用操作符delete
​ 語法: new 數據類型
​ 利用new創建的數據,會返回該數據對應類型的指針

示例1: 基本語法

int* func()
{
    int* a = new int(10);
    return a;
}
 
int main() {
 
    int *p = func();
 
    cout << *p << endl;
    cout << *p << endl;
    //利用delete釋放堆區數據
    delete p;
    //cout << *p << endl; //報錯,釋放的空間不可訪問
    system("pause");
    return 0;
}

示例2:開闢數組

//堆區開闢數組
int main() {
 
    int* arr = new int[10];
 
    for (int i = 0; i < 10; i++)
    {
        arr[i] = i + 100;
    }
    for (int i = 0; i < 10; i++)
    {
        cout << arr[i] << endl;
    }
    //釋放數組 delete 後加 []
    delete[] arr;
    system("pause");
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章