類在內存中結構——虛函數,派生類

關於類的大小,請先查看:
類和結構體的內存空間佔有問題

簡介

C++類是由結構體發展得來的,所以他們的成員變量(C語言的結構體只有成員變量)的內存分配機制是一樣的。

高字節與低字節,高地址與低地址,大端模式與小端模式

一、高地址與低地址

內存地址對應成16進制,值大的是高地址,反之爲低地址。
高地址、低地址

二、高字節與低字節

如int a=16777220,化爲十六進制是0x01 00 00 04則04屬於低字節,01屬於高字節

三、大端模式與小端模式

大端模式:高字節存放在低地址
大端模式
小端模式:高字節存放在高地址
小端模式

四、存放順序

  1. 一個整數類型內部
    低地址存儲低位,高地址存儲高位。比如int a=1,則存儲情況爲0000(高地址) 0000 0000 0001(低地址)
  2. 若干個局部變量(在棧中存儲的)
    先定義的高地址,後定義的低地址
  3. 類、結構體或數組的元素
    先定義的低地址,後定義的高地址

union U {
    char cp[2];
    short sp;
};
int main(int argc, char *argv[])
{
    U temp;
    temp.cp[1] = 1;
    temp.cp[0] = 3;
    cout << temp.sp << endl;
    return 0;
}

結果:

259		// 0x0103 小端模式

int main(int argc, char *argv[])
{
    int a;
    char b;
    int c;
    short d;
    long int e = 1;
    char *p;

    cout << "int &a =  " << (size_t)&a << endl;//結果1
    cout << "char&b =  " << (size_t)&b << endl;//結果2
    cout << "int &c =  " << (size_t)&c << endl;//結果3
    cout << "short&d = " << (size_t)&d << endl;//結果4
    cout << "long &e = " << (size_t)&e << endl;//結果5
    cout << "char*&p = " << (size_t)&p << endl;//結果6

    char temp[16]={0};
    memcpy(temp, &p, 16);
    cout << (size_t)p << endl;
    for ( int i = 0; i < 16; i++) {
        cout << (int)temp[i] << " ";
    }
    cout << endl;
    return 0;
}

結果:

int &a =  140722993149544
char&b =  140722993149543
int &c =  140722993149536
short&d = 140722993149534
long &e = 140722993149520
char*&p = 140722993149512
4233981
-3 -102 64 0 0 0 0 0 1 0 0 0 0 0 0 0 

分析:
可以看見,局部變量從高地址開始分配,到低地址。

結果1 > 結果2 > 結果3 > 結果4 > 結果5 > 結果6
結果1 - 結果2 = 140722993149544 - 140722993149543 = 1B
	//一個char佔一個字節的內存
結果3 + 4B = 140722993149540
	//一個字節的變量必須對齊,填充三個字節
結果5 - 結果6 = 140722993149520 - 140722993149512 = 8B
	/* 
	char *佔4個字節,但是內存分配了8個字節;
	我們把內存打印出來:
	4233981
	-3 -102 64 0 0 0 0 0 1 0 0 0 0 0 0 0
	可以看見,指針後面自帶了一個字節的空字符
	*/

單個指針和數組名指針有一點不同,那就是
單個指針有一個存儲空間,且自帶'\0'結束符(如上),它的存儲內容和地址不一樣的

char *p;
&p != p

數組名指針,它的指向的地址都是在數組首地址

char a[10];
&a == a;

關於數組聲明後再內存中的分配問題,作者實驗了很久,發現同樣的代碼,連續幾次編譯後得到的結果,都是不一樣的。
尤其是當有int[]數組時,甚至出現違背第二條內存分配原則,int[]數組總是被分配在最低的地址處。
作者猜測,這應該和編譯器優化掛鉤的。

虛函數

有虛函數的類裏,有一張虛函數表,這張表裏是每個虛函數的函數指針。對,它的大小就是所有指針加起來的大小。
這些指針放在類實例地址的低地址,也就是類對象頭部。
然後就是各個變量。

派生類

在這裏插入圖片描述
如上圖,子類實例化後的結構。
他有多少個父類每個父類的大小加起來在加上自身就是sizeof的大小。
話句話說,對於子類,最開始的內存數據記錄着父類對象的拷貝(包括父類虛函數表指針和成員變量)。 之後是子類自己的成員變量數據。

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