8. C++記憶體模型
每個程式執行起來以後,它將擁有自己獨立的虛擬地址空間。
這個虛擬地址空間的大小與作業系統的位數有關係。
例如32位硬體平臺的虛擬地址空間的地址可以從0 2^32-1,即0x00000000 0xFFFFFFFF,總共4GB大小。
在32位Windows作業系統中,高地址的2GB位核心空間,使用者空間只有2GB,
而32位Linux的核心空間只有1GB,使用者空間有3GB大小。
而64位作業系統,使用者可用空間則要大的多。

image.png
C++記憶體分佈:
1)棧區:由編譯器自動分配釋放 ,存放函式的引數值,區域性變數的值等。其操作方式類似於資料結構中的棧。 (向下增長,地址由高到低)
2)堆區,一般由程式設計師分配釋放, 若程式設計師不釋放,程式結束時可能由系統回收 。注意它與資料結構中的堆是兩回事,分配方式倒是類似於連結串列。(向上增長,地址由低到高)
3)全域性區(靜態區)(static):全域性變數和靜態變數的儲存是放在一塊的,初始化的全域性變數和靜態變數在一塊區域, 未初始化的全域性變數和未初始化的靜態變數在相鄰的另一塊區域(bss段), 程式結束後由系統釋放。
4)文字(只讀)常量區:常量字串就是放在這裡的,程式結束後由系統釋放 。
5)程式碼段文字(text)區,存放程式碼的區域,如函式體(類成員函式和全域性函式)的二進位制程式碼。
文字常量和常變數
文字常量又稱為“字面常量”,包括數值常量、字元常量和符號常量。其特點是編譯後寫在程式碼區,不可定址,不可更改,屬於指令的一部分。因此像如下的程式碼是無法編譯的:
int& r=1; //error: invalid initialization of non-const reference of type 'int&' from an rvalue of type 'int'
但是如下程式碼確實可以通過編譯的。主要原因是const int _r=1;_r儲存在只讀常量區,對其建立引用自然是合理的。
const int& r=1;
文字常量的主要型別如下圖所示:

image.png
常變數指定義時必須顯示初始化且值不可修改的變數。與普通變數一樣被分配空間,因此是可以定址的。鑑別常變數的一個簡單方法是檢視變數是否有const關鍵字。
常變數包括全域性常變數和區域性常變數。
二者的區別在於:
1.全域性常變數儲存在只讀常量區,其不可修改性由作業系統保障。
2.區域性常變數儲存在棧區,其不可修改性僅僅是由編譯器來保證,因此可以用const_cast
字串和字元陣列的儲存位置
#include <iostream> #include <string.h> using namespace std; char *returnStr() { static char p[] = "hello world!";//雖然是函式內部,但是由於是static,儲存在全域性區(靜態區) return p; } char *returnArray() { char p[] = "hello world!";//hello world!在只讀資料段,但同時在棧上也會開闢一塊空間,然後複製進去 return p;//事實上返回了棧記憶體 } int main() { char str1[] = "hello,world";//棧區,執行時賦值 char str2[] = "hello,world";//棧區 const char str3[] = "hello,world"; const char str4[] = "hello,world"; const char *str5 = "hello,world";//字串常量,只讀常量區 const char *str6 = "hello,world";//只讀常量區 return 0; }