2016-04-12 67 views
0

對於一個簡單的C++程序。類對象的成員函數的內存分配

#include <iostream> 
#include <string> 
using namespace std; 

class Student 
{ 
    float gpa; 
    public: 
    void read() 
    { 
     cin>>gpa; 
    } 

    void display() 
    { 
      cout<<"STUDENT GPA : "<<GPA<<endl; 
    } 
}; 

void main() 
{ 
    Student s1; 
} 

對於對象s1,必須在主存儲器中分配4個字節。但是,當選中時,分配的內存略高於4個字節,因爲成員函數,構造函數和析構函數會分配一些內存。如何計算所有函數的大小,並且是否可以通過減少這些額外分配來優化代碼。

+0

你的意思是's1'的大小高於'float'的大小?你是怎麼檢查的?每個函數都需要一些空間,但是這些空間與's1'分開。函數的大小是生成的機器碼的大小。這些不能超越編譯器的優化。 – freakish

回答

1

首先,這顯然是實施細節。我的意思是不同的編譯器或編譯選項可能會導致不同的值。 但是,因爲在這裏沒有虛函數(*),所以方法,構造函數和析構函數不應該在對象本身中需要任何空間。

和(固定在你的代碼中的一些錯誤和警告後:mainint,而不是void,並GPAgpa ...)只顯示在32位架構sizeof(鐺版本3.4.1):

int main() 
{ 
    Student s1; 
    cout << "Size: " << sizeof(s1) << endl; 
    return 0; 
} 

顯示器...:

Size: 4 

但是它可能是8上的64位體系結構或如果使用#pragma pack(8) (*)仍然是實現細節,但虛擬函數通常實現爲虛擬表。這意味着對象包含一個指向該對象的虛擬函數的表的指針(只有一個指針),或者直接包含該表的一個副本(每個虛擬函數一個指針)。構造函數不是虛擬的,不佔用空間,但虛擬析構函數在vtable中使用一個入口。

+0

感謝您的回答。我已經明白你的話了。但我有一個疑問。假設我在Student類中有虛函數,構造函數和析構函數將如何佔用對象中的空間?它如何依賴於虛擬功能? –

+0

「Student」是POD意味着這不是實現細節嗎? – svick

+1

@svick每個字段的大小和填充是實現細節... –

2

但檢查時,分配的內存比4個字節

正確略高。

因爲成員函數,構造函數和析構函數會分配一些內存。

不正確。這是因爲在你的情況下內存對齊需求,而在其他情況下,因爲虛函數需要某種形式的表,需要一個指向它的指針。構造函數和析構函數以及方法的內存成本只支付一次,而不是按對象支付。

如何是所有功能

計算出它的大小是沒有的。

是否有可能通過減少這些額外的分配來優化代碼。

當然,但這對sizeof一個對象沒有影響。

1

對於對象s1,必須在主存儲器中分配4個字節。

他們沒有。您只能在單個函數內使用該對象,不要使用指針或引用來操作它,並且它只包含一個單獨的字段,因此編譯器可能決定將該字段存儲在寄存器中,而不是存儲器中。

此外,您實際上並沒有使用該字段,因此編譯器可能根本不分配變量和字段,因爲它是不可觀察的優化。

爲了證明這一點,你可以在disassembly of your code看(用在x64鐺3.3 -O3):

main: 
     xorl %eax, %eax 
     ret 

注意,所有這些代碼不會是零時的EAX寄存器,它僅僅是個隱性return 0;