C++ c++;带函数的结构的大小

C++ c++;带函数的结构的大小,c++,struct,sizeof,C++,Struct,Sizeof,结果显示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; } #包括

结果显示
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;
}
#包括
使用名称空间std;
结构ABC_{
INTA;
int b;
INTC;
intfoobar(inta){
返回a;
}
};
int main(){
ABC_uuABC;

CUT< P>函数<代码> FoBOAR 不是对象的一部分,而是编译程序的一部分。当函数被调用时,机器代码是指它的地址。

<代码> siZOFF()>代码>将只考虑成员变量。

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

您的
结构类似于

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

在现有答案的基础上增加:


另外值得注意的是,具有虚拟方法的类要大8个字节(或系统上指针的字节数)。这是指向带有虚拟方法地址的表的指针。这是程序在运行时如何知道要调用哪个版本的虚拟方法。

函数存储在
.text
段中

编译程序的内存分为五段:文本, 数据、bss、堆和堆栈。每个段表示一个特殊部分 为特定目的而保留的内存。文本段是 有时也称为代码段。这是汇编代码的地方 程序的机器语言指令位于

对象本身的内存布局为:

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;
    }
};
当类包含虚拟函数时,它们以相同的方式存储,但类的内存布局发生变化…它将有一个不可见的4字节(32位)指针指向虚拟函数表或虚拟方法表/VMT(此表仅保存函数的地址以允许多态性,当它继承存储在内存中的另一个表时,将分别为每个类创建此表),因此在这种情况下,大小将为16。它还取决于编译器的对齐设置

如果要获取指向vtable的指针,可以通过以下方式执行:

void **get_vtable(void *obj) {
    return *(void ***)obj;
}
Vtable通常存储在我所知道的每个编译器的开头

当函数是虚拟函数时,您可以通过查看调用方式来注意到它与非虚拟函数的区别。普通函数直接调用/jmped,而虚拟函数则由存储在表中的函数指针调用

(我脑子里想不出某些x86 asm,可能是错的)

或者干脆

mov edx, [ecx+12h]
call edx

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

这是什么:
intfoobar(ABC_*this->a)
?现在每个人都可以调用
foobar(inta)
,即使是
ABC_
虚拟方法的对象也没有任何贡献(除了vptr)下面是一本关于对象模型的好书:添加:在大多数实现中,vptr隐式地放在类/结构布局的开头。
mov edx, [ecx+12h]
call edx