具有函数的结构的c ++大小

c++ size of a struct with a function

结果显示 12
函数 foobar 存储在内存中的什么位置?

#include <iostream>
using namespace std;
struct ABC_ {
    int a;
    int b;
    int c;
    int foobar(int a) {
        return a;
    }
};
int main() {
    ABC_ ABC;
    cout << sizeof ABC;
    return 0;
}

函数foobar不是对象的一部分。相反,它是已编译程序的一部分。调用函数时,机器码指的是它的地址。

sizeof() 将只考虑成员变量。

此外,非 vptr 方法不会影响结构的大小,因为它们不需要任何运行时支持。

您的 struct

相似
struct ABC_ {
    int a;
    int b;
    int c;
};
int ABC_::foobar(int a) {
    return a;
}

添加到现有答案:

另外值得注意的是,类 与虚拟方法相比,要大 8 个字节(或者无论您系统上的指针有多少字节)。这是一个指向 table 的指针,其中包含虚拟方法的地址。这就是程序在运行时如何知道要调用哪个版本的虚拟方法。

该函数存储在 .text 段内。

A compiled program’s memory is divided into five segments: text, data, bss, heap, and stack. Each segment represents a special portion of memory that is set aside for a certain purpose. The text segment is also sometimes called the code segment. This is where the assembled machine language instructions of the program are located.

对象本身的内存布局为:

class ABC_ {
public:
    int a; // 0x4 (4)
    int b; // 0x8 (8)
    int c; // 0xC (12)
    int foobar(int a) { // you can print address using &foobar
        return a;
    }
};

当你的 class 包含虚函数时,它们以相同的方式存储,但你的 class 的内存布局发生变化......它将有一个不可见的 4 字节(32 位)指针到虚函数 table 或虚方法 table/ VMT (这个 table 只是保存函数的地址以允许多态性,例如 table 是为每个 class 单独创建的,当它继承另一个 table 存储在内存中时)所以在这种情况下大小将为 16。它还取决于编译器的对齐设置...

如果你想获得指向 vtable 的指针,你可以这样做:

void **get_vtable(void *obj) {
    return *(void ***)obj;
}

Vtable 通常存储在我所知道的每个编译器的开头。

通过查看函数的调用方式,您可以注意到函数为虚函数和非虚函数时的区别。普通函数直接 called/jmped 但虚拟函数,它们由存储在 table.

中的函数指针调用

(我脑子里的一些 x86 asm,可能是错误的)

mov edx, [ecx] // ecx = this pointer
add edx, 12h // let's say 0x12 is the offset divided by 4 is 4 = index in vtable
call edx // you know it's virtual function

或干脆

mov edx, [ecx+12h]
call edx

了解事物如何存储在内存中的最佳方法是使用一些反汇编程序 and/or 调试器。我推荐 IDA Pro 和 x64dbg。