我有以下代码片段:
Class Sample
{ Obj_Class1 o1;
Obj_Class2 o2;};
但是Obj_Class1
和Obj_Class2
的大小非常大,因此编译器会显示警告“考虑将一些空间移动到堆中”。我被要求用Obj_Class1* o1 = new Obj_Class1();
替换 Obj_Class1 o1。但我认为这种更改没有用处,因为如果堆栈分配失败,堆分配也会失败。我正确吗?或者进行此更改是否有意义(除了抑制编译器警告)。
我有以下代码片段:
Class Sample
{ Obj_Class1 o1;
Obj_Class2 o2;};
但是Obj_Class1
和Obj_Class2
的大小非常大,因此编译器会显示警告“考虑将一些空间移动到堆中”。我被要求用Obj_Class1* o1 = new Obj_Class1();
替换 Obj_Class1 o1。但我认为这种更改没有用处,因为如果堆栈分配失败,堆分配也会失败。我正确吗?或者进行此更改是否有意义(除了抑制编译器警告)。
栈比堆小是非常典型的情况,它们使用不同的内存位置。栈通常大小约为1MB(您可以更改它,但要小心),并且为每个线程分配。堆可在需要时消耗几GB。
栈通常很小,不适合存储大型对象,而堆是单独设计用于存储它们的。
在您的样例中,您应该将整个Sample
分配到堆上,而不是其成员:
int main() {
Sample* sample = new Sample();
}
默认情况下,堆栈相对较小:http://msdn.microsoft.com/en-us/library/ms686774(VS.85).aspx
保留和最初分配的堆栈内存的默认大小在可执行文件头中指定。如果没有足够的内存来保留或提交所请求的字节数,则线程或纤程创建将失败。链接器使用的默认堆栈保留大小为1 MB。要为所有线程和纤程指定不同的默认堆栈保留大小,请在模块定义(.def)文件中使用STACKSIZE语句。操作系统将指定的大小舍入到系统分配粒度的最近倍数(通常为64 KB)。要检索当前系统的分配粒度,请使用GetSystemInfo函数。
在Visual Studio中,默认情况下,每个线程都会获得1 MB的空间,如果您尝试分配超过这个大小的空间,就会出现堆栈溢出错误。堆没有这个限制,您可以分配的内存量取决于进程虚拟内存中最大的连续空间。因此,如果对象非常巨大,则堆栈分配失败并不奇怪。