编译器如何为类分配内存?

4
当我用类指针创建一个类时,例如:
class A{
    B* p_b1;
    B* p_b2;
    A(){}
}

我假设编译器为每个A实例生成至少2个指针大小的空间。我的问题是,如果它们不是指针,而是像这样的普通对象:

class A{
    B b1;
    B b2;
    A(){}
}

编译器会在A类的内存空间中分配b1和b2的空间吗?还是它会在堆栈的其他位置声明实际的B类?

我问这个问题是因为我正在尝试减少代码中的内存分配,想知道是否会有任何区别。


你在堆栈的其他地方指的是什么?在你的例子中,b1、b2 是在堆栈上创建的。如果你想减少内存分配,那么使用较少的对象(包括在堆上创建的对象)。 - Nandu
编译器从不分配空间,运行时才会分配! - Nandu
@Nandu 是的,但是机器需要为每个对象在堆栈上分配内存。因此,我不得不问它是否会将分配泛化以覆盖所有对象。本质上是“共享”堆栈分配。 - sgtHale
@tweej 不,我非常清楚如何使用动态内存分配。这是特别针对堆栈分配的。 - sgtHale
在这种情况下,对于您的第二种情况,对象在堆栈上的位置并不重要。如果支持A及其成员的页面足够大,则不需要分配更多的内存页面。如果映射堆栈的区域不够大,则会出现页面错误,然后由内核分配更多的内存页面直到堆栈限制。对于您的第一种情况,这取决于A的构造函数是否分配新的B对象,还是只复制指向已存在的B对象的指针。这些是操作系统内存管理实现细节。 - tweej
显示剩余2条评论
2个回答

4
编译器会在 A 类的内存空间中为 b1 和 b2 分配空间吗?
答案是肯定的。
它会在堆栈中声明实际的 B 类吗?
不会。
我问这个问题的原因是因为我想减少代码中的内存分配,不知道是否有任何区别。
是的,有区别。在堆栈上分配内存要比从堆上分配内存更高效。如果可以,当性能成为问题时,请优先使用堆栈进行内存分配。

这不是要看问题而定吗?例如:对象的向量 vs 指针的向量 - 堆栈 vs 堆。 - Nandu
第二个例子更高效,即使类A的对象在堆上创建,它只需要一次堆分配而不是三次。 - Gort the Robot
@Nandu,当你有一个对象向量时,栈上没有太多东西。大部分内存在堆上。如果你有一个指针向量,你有两个级别的堆内存,一个是为向量“数据”分配的内存,另一个是为对象本身分配的内存。 - R Sahu
但是当性能成为问题时,最好选择堆栈而不是堆。那么这如何适用于增长的向量(或STL容器)?在这些情况下,将对象放在堆上是否提供更好的性能呢? - Nandu
@Nandu,在使用向量时,您无法选择“数据”分配的位置,它总是在堆上。这并不比使用堆栈内存创建的数组提供更好的性能。它会带来其他好处-动态调整大小、能够创建更大的数组等。但是它不会比在堆栈上创建一个数组表现得更好。 - R Sahu

0

这实际上取决于情况。任何作为对象字段的东西都会以与对象相同的方式分配(无论是在堆栈上还是在堆上)。如果您想减少分配,可以考虑重用对象。您可以手动调用析构函数,然后调用放置 new表达式来重用对象的内存。

另一方面,如果您只是想减少使用的堆栈大小,则在构造函数中在堆上分配,在析构函数中释放(RAII)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接