这种类型的内存是在堆还是栈上分配的?
Posted
技术标签:
【中文标题】这种类型的内存是在堆还是栈上分配的?【英文标题】:Does this type of memory get allocated on the heap or the stack? 【发布时间】:2010-09-30 09:59:27 【问题描述】:在 C++ 的上下文中(没关系):
class Foo
private:
int x[100];
public:
Foo();
我所学到的告诉我,如果你像这样创建一个 Foo 的实例:
Foo bar = new Foo();
那么数组 x 是在堆上分配的,但是如果你像这样创建了一个 Foo 的实例:
Foo bar;
然后在堆栈上创建它。
我在网上找不到资源来确认这一点。
【问题讨论】:
【参考方案1】:是的,如果您在堆上创建Foo
对象,则会在堆上创建成员数组x
。当您为Foo
分配动态内存时,您要求的内存长度为sizeof(Foo)
(可能还有一些内存开销,但我们暂时忽略它),这在您的示例代码中意味着100 int
s 的大小.这必须在Foo
类型的对象(及其内部数据)的生命周期内跨越范围。
如果您不在堆上创建Foo
对象,并且Foo
的内部数组不是您在Foo
的构造函数中使用new
分配内存的指针,那么内部数组将在堆栈上创建。同样,为了在范围结束时自动清理阵列而没有任何delete
s,必须是这种情况。具体来说,
struct Foo
int* y;
Foo() : y(new int())
~Foo() delete y;
;
将在堆上创建y
,无论Foo
对象是在堆栈上还是在堆上创建。
【讨论】:
【参考方案2】:严格来说,根据标准,对象不必存在于堆栈或堆中。该标准定义了 3 种类型的“存储持续时间”,但没有明确说明必须如何实现存储:
-
静态存储时长
自动存储时长
动态存储时长
自动存储持续时间通常(几乎总是)使用堆栈实现。
动态存储持续时间通常使用堆实现(最终通过malloc()
),但即使编译器的用户也可以覆盖它。
静态存储持续时间通常称为全局变量(或静态存储)。
标准对这些事情有这样的说法(以下是 3.7 - Storage Duration 的各个部分的摘录):
静态和自动存储期限 与引入的对象相关联 通过声明(3.1)和隐式 由实现(12.2)创建。 动态存储时长为 与创建的对象相关联 新运算符 (5.3.4)。
...
所有没有动态的对象 存储期限也没有本地有 静态存储时间。存储 对于这些对象应持续 计划的持续时间(3.6.2, 3.6.3)。
...
本地对象显式声明为 auto 或注册或未明确声明 静态或外部有自动 储存期限。存储为 这些对象持续到块 它们被创建的出口。
...
对象可以动态创建 在程序执行期间(1.9),使用 新表达式(5.3.4),并销毁 使用删除表达式 (5.3.5)。交流电 + + 实现通过以下方式提供对动态存储的访问和管理 全局分配函数 运算符 new 和 operator new[] 和 全局释放函数 运算符删除和运算符删除[]。
...
库提供默认 全局分配的定义 和释放功能。一些 全局分配和释放 功能可替换 (18.4.1)
最后(关于示例类中的数组):
3.7.4 子对象的持续时间 [basic.stc.inherit]
成员子对象、基类子对象和数组元素的存储时长是它们完整的存储时长 对象 (1.8)。
【讨论】:
【参考方案3】:对您的示例稍作修改:
class Foo
private:
int x[100];
int *y;
public:
Foo()
y = new int[100];
~Foo()
delete[] y;
示例 1:
Foo *bar = new Foo();
x 和 y 在堆上:
sizeof(Foo*) 在堆栈上创建。
sizeof(int) * 100 * 2 + sizeof(int *) 在堆上
示例 2:
Foo bar;
x 在栈上,y 在堆上
sizeof(int) * 100 在栈上 (x) + sizeof(int*)
sizeof(int) * 100 在堆上 (y)
实际大小可能会因类/结构对齐而略有不同,具体取决于您的编译器和平台。
【讨论】:
您对如何得出结论有任何建议的参考资料吗?我的印象与 OP 相同;调用new
会在堆上为数据动态分配内存。否则,像Foo bar
这样的调用会将本地数据压入堆栈。无论哪种情况,我都希望类指针严格分配在堆栈上。修饰符public
和private
对分配方式有何影响?【参考方案4】:
你是说
Foo* bar = new Foo();
我想。 那个是在堆中创建的。
【讨论】:
【参考方案5】:Foo 类型的对象按顺序存储 100 个整数。 如果你在堆栈上创建它,你将把它全部放在堆栈上。 如果您使用 new 执行此操作,它将作为对象的一部分在堆上。
这是语言规范的一部分,我不确定您的问题是什么。
【讨论】:
也许他在问语言规范的哪一部分是这样说的 :-)以上是关于这种类型的内存是在堆还是栈上分配的?的主要内容,如果未能解决你的问题,请参考以下文章