c++ sizeof對象大小整理


1. sizeof 是運算符,而不是函數。

2. 當sizeof 的對象是表達式時,求的大小是表達式返回值的類型大小,但並不計算表達式的值,比如:

1 char c = 1;
2 int i = 2;
3 cout << sizeof(c + i) << endl;
4 cout << sizeof(c = c + i) << endl;

前者c + i會隱式類型轉化為int類型(類型提升),因此返回4(32位系統), 而后者雖然運算時也是轉化為int,但賦值給c時又會轉化為char,因此返回的是1。

3. 如果對象是函數,則返回函數返回值類型大小,如:

 1 long long foo()
 2 {
 3     cout << "foo() has been called" << endl;
 4     return 0;
 5 }
 6 
 7 int main(int argc, char **argv)
 8 {
 9     cout << sizeof(foo()) << endl;
10     return 0;
11 }

執行后輸出8, 不會輸出 foo() has been called.說明函數沒有真正執行,而只是判斷了下返回類型。

4. 當sizeof的對象是數組時,返回數組總大小,而當對象是指針時,返回指針本身的大小,而不是指示內存空間的大小。因為指針本身就是一個無符號整型數, 因此int *p ,sizeof(p)返回的大小是sizeof(void *), 32 位系統返回4,即32位。但注意當數組名作為實參傳入函數時,會自動轉化為指針類型,如下:

 1 void foo(int a[])
 2 {
 3     cout << sizeof(a) << endl; /* 4 */
 4 }
 5 int main(int argc, char **argv)
 6 {
 7     int a[] = {1, 2, 3, 4};
 8     int *p = a;
 9     cout << sizeof(a) << endl; /* 16 */
10     cout << sizeof(p) << endl; /* 4 */
11     foo(a);
12     return 0;
13 }

5. sizeof 無法獲取動態分配的內存大小,即使用malloc動態的分配內存,無法使用sizeof獲取其大小。

6. 注意c_style字符串末尾有一個\0結束符,也需要占一個char空間,因此sizeof("1") 返回2。而strlen返回的是字符數,不包括\0結束符。

7. 理論上一個結構體所占空間是所有成員的大小總和,但由於考慮到對齊問題,會有填充字節。

struct node1
{
    int a;
    int b;
    char c;
    char d;
};

struct node2
{
    int a;
    char b;
    int c;
    char d;
};

node1大小為12字節, node2大小為16字節。

結構體后面的動態數組,即不指定大小的數組,sizeof 時不包括動態數組的大小,即

1 struct node
2 {
3     int a;
4     char c;
5     int d[];
6 };

返回依然是8。

8. 類的大小:

 (1). 空類的大小。空類型實例中不包含任何信息,應該大小為0. 但是當我們聲明該類型的實例的時候,它必須在內存中占有一定的空間,否則無法使用這些實例。至於占用多少內存,由編譯器決定。g++中每個空類型的實例占1字節空間。注意空struct即空類,這就是為什么c++的空struct占1個字節的原因。

 (2). 構造函數、析構函數、成員函數調用時只需知道函數地址即可,而這些函數的地址之與類型相關,而與具體的實例無關,因此不會在實例中額外添加任何信息。

 (3). 靜態數據成員放在全局數據成員中,它不占類實例大小,多個類實例只有一個實體。可以看作是一種特殊的全局變量。

 (4). 類的非靜態數據成員和struct類似,也需要對齊,可能需要字節填充。

 (5). 如果一個類中有虛函數,則該類型會生成一個虛函數表,並在該類型的每一個實例中添加一個指向虛函數表的指針,因此類大小必須加上一個指針所占的空間。如果是普通繼承,子類和基類共享這個指針。

 1 class A
 2 {
 3     public:
 4         static int a;
 5         static char c;
 6         A(){};
 7         ~A(){};
 8         void foo(){};
 9 }; 
10 // 類A的大小為1字節,等於空類大小,靜態數據成員a、c和成員函數都不占類的大小。
11 
12 class B
13 {
14     public:
15         int a;
16         char c;
17         A(){};
18         ~A(){};
19         void foo(){};
20 };
21 // 類B的大小為8字節
22 
23 class C
24 {
25     public:
26         int a;
27         char c;
28         A(){};
29         ~A(){};
30         void foo(){};
31         void virtual bar(){};
32 };
33 // 類C的大小為12。數據成員8,加上指向虛擬函數表的指針。

 

(感謝http://www.cnblogs.com/zhangyz/articles/4736758.html)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM