类对象的成员函数的内存分配

Memory allocation of member functions of a class object

本文关键字:内存 分配 函数 成员 对象      更新时间:2023-10-16

对于一个简单的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字节,因为成员函数、构造函数和析构函数分配了一些内存。!如何计算所有函数的大小,是否可以通过减少这些额外的分配来优化代码。?

但当检查时,分配的内存略高于4字节

正确。

因为成员函数、构造函数和析构函数会分配一些内存。

不正确。这是因为在您的情况下需要内存对齐,在其他情况下是因为虚拟函数需要某种形式的表,该表需要一个指向它的指针。构造函数、析构函数和方法的内存成本是一次性支付的,而不是每个对象。

所有功能的大小是如何计算的

事实并非如此。

有可能通过减少这些额外的分配来优化代码吗。?

当然,但这对sizeof对象没有影响。

首先,这显然是一个实现细节。我的意思是,不同的编译器或编译选项可能会导致不同的值。但是,由于这里没有虚拟函数(*),因此方法、构造函数和析构函数在对象本身中不需要任何空间。

并且(在修复了代码中的一些错误和警告之后:main应该是int而不是voidGPA应该是gpa…)只在32位架构上显示sizeof(clang版本3.4.1:

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

显示…:

Size: 4

但在64位体系结构上,或者如果使用#pragma pack(8) ,它可能是8

(*)仍然是一个实现细节,但虚拟函数通常被实现为vtables,即虚拟函数表。这意味着该对象包含指向该对象的虚拟函数表的指针(只有1个指针),或者直接包含该表的副本(每个虚拟函数一个指针)。构造函数不是虚拟的,也不占用任何空间,但虚拟析构函数使用vtable中的一个条目。

对于对象s1,必须在主内存中分配4个字节。

他们没有。您只在单个函数中使用对象,不使用指针或引用对其进行操作,并且它只包含一个float字段,因此编译器可能决定将该字段存储在寄存器中,而不是存储在内存中。

此外,您实际上并没有使用该字段,因此编译器可能根本没有分配变量和字段,因为这是一种不可观察的优化。

要显示这一点,您可以查看代码的反汇编(在x64上使用带有-O3的clang 3.3):

main:
        xorl    %eax, %eax
        ret

请注意,这些代码所做的只是将EAX寄存器清零,这只是隐含的return 0;