You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++中对象进入作用域时,栈中究竟存入了哪些内容?

栈上对象的底层存储细节

1. 栈上对象的本质

栈上的对象就是一块连续的栈内存区域,大小等于对象的实例总大小(成员变量的大小之和加上编译器为内存对齐添加的填充字节)——成员函数不占实例空间。进入作用域时,栈指针(如x86的ESP、x86_64的RSP)向下移动对应长度,完成空间分配;退出作用域时栈指针上移,自动回收空间。

2. 成员变量的存储规则

  • 基础类型与指针:成员变量会按类定义的顺序存储,但编译器会做内存对齐优化。比如32位系统中,int(4字节)后紧跟double(8字节)时,编译器会在int后填充4字节空白,确保double的起始地址是8的倍数,让CPU能高效访问。
  • 嵌套对象成员:如果成员是完整对象(比如示例里的sub_obj),它的所有成员会直接嵌入当前对象的栈空间,相当于把SomeOtherClass的内存布局完整“嵌入”到MyClass的对应位置,同样遵循内存对齐规则。
  • 指针成员:像some_map这种指针,栈上只存一个指针值(32位4字节,64位8字节),指向堆上实际的std::unordered_map对象,栈里不会放这个map的实际数据。

3. 成员函数的底层处理

成员函数不会存在对象的栈空间里:

  • 非虚成员函数:整个类的所有实例共享同一份函数代码,程序启动时就被加载到代码段(Text Segment)。调用时,编译器会把对象的指针/引用作为隐式参数(即C++的this指针)传递给函数,函数通过this访问对象成员,不需要在栈里存储函数地址。
  • 虚函数:类会生成一张虚函数表(vtable,存在只读数据段),每个对象的栈空间开头会有一个指向虚表的指针(vptr)。调用虚函数时,先通过vptr找到虚表,再从表中取出对应函数地址执行。

4. 示例场景的栈内容分析

当调用function(const MyClass& obj)时,栈上存入的是**obj引用对应的地址值**(32位4字节,64位8字节)——因为引用本质是指针的语法糖。如果是传值调用(function(MyClass obj)),栈上会存入MyClass的完整实例:

  • 按内存对齐后的顺序存放a、填充字节(若需要)、b、some_map指针、sub_obj的所有成员(含对齐空间)。
  • 注意:DoSomething的代码不在栈上,调用它时只是跳转到代码段的对应地址执行,同时传入当前对象的this指针。

拓展阅读

  • 《深入理解计算机系统》:详细讲解内存布局、栈的工作机制、编译器内存对齐策略。
  • 《C对象模型》:专门剖析C类对象的底层存储、成员函数调用逻辑、虚表实现细节。
  • 《汇编语言》:通过汇编代码观察函数调用时的栈变化,理解参数传递和对象存储的底层过程。

内容的提问来源于stack exchange,提问作者Joe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 16:33:42