为什么类大小只取决于数据成员而不取决于成员函数

Why class size depend only on data members and not on member functions?

本文关键字:取决于 成员 函数 数据成员 为什么      更新时间:2023-10-16

我想知道关于类大小的详细描述。我想知道是否只有数据成员&没有任何虚拟关键字的成员函数,那么为什么类大小只取决于数据成员。例如:

class A {
    int a;
public:
    int display() { 
    cout << "A=" << a << endl;
   }
};

当我检查sizeof(A)时,我发现它是4字节。为什么会这样?为什么成员函数对A类的大小没有影响?

感谢

因为类的函数没有保存在对象本身内部。从C编程的角度来看,A类的每个函数都有一个秘密参数,即this指针,所以实际上它们只是带有一个额外参数的函数。

例如,想象一下:

int display(A* thisptr)
{
   //do something
   printf("%d",thisptr->a); 
   return;
}

因此,显示函数被保存为一个带有一个额外参数的简单函数。不过,根据编译器的不同,名称会被篡改。

我相信不同的规则适用于涉及函数指针的虚拟函数,但由于我不确定其他人是否能在这件事上启发我们。

这取决于实现-标准中没有指定。然而,你是对的,非虚拟成员函数(甚至是第一个之后的虚拟函数)不会影响类大小。

这是因为如果类的每个实例都有指向所有函数的指针,那么它将占用大量内存。他们为什么会这样做?在运行时,对象知道它是什么类型,并且可以调用适当的函数。同一个函数在不同的实例中是相同的,不同的是它所操作的对象,它作为一个参数在后台传递。

函数/方法存储为代码,而不是数据。就像一个可执行文件存储为单个文件一样,可以多次启动,并且它的多个实例将具有不同的数据。类似地,函数是和可执行代码,并且您传递给它的数据可能不同(对于相同的文字处理软件,类似于不同的文档)。

可执行代码不会有任何sizeof,因为当程序运行时,它们不会占用堆栈或堆上的空间。它本身存储在可执行映像中,并在启动程序时由操作系统加载一次。

就像普通的C函数一样,C++方法只是内存中的一个地址,供调用时执行跳转到该地址。唯一的区别是第一个参数,它是指向调用函数的对象的指针。

除了为实现虚拟函数和虚拟继承而引入的隐藏数据成员外,实例大小完全由类的数据成员和基类决定来自C++:Under the Hood(1994)如果你想了解更多。

成员函数是流程文本段的一部分,对象是流程数据段的一部份。因此,由于对象只是数据,它通过添加类中所有数据成员的大小来计算大小。成员函数对所有对象都是通用的,它的区别仅在于特定对象指针(称为该指针)的第一个参数,该指针作为隐藏指针传递给类的每个成员函数。

因为函数状态留在堆栈中,并在函数进入/退出时创建/删除。

在对象的大小中,只有有助于存储对象状态的成员。函数只是一段从给定点开始的代码,它不依赖于它所引用的特定对象实例

思考

A a1, a2;

a1.a和a2.a是不同的,但是a1.display()和a2.dispay()是相同的函数代码(将int A::display())视为int display(A* this)