7

我一直在寻找在 C++ 中在堆栈或堆上分配对象的经验法则。我在这里找到了很多关于 SO 的讨论。很多人说,这关乎一个物体的生命周期。如果您需要比函数范围更长的生命周期,请将其放入堆中。这很有意义。

但是让我感到困惑的是,许多人说,如果对象很小,就将它们分配给堆栈。如果对象很大,则将其放入堆中。但是他们都没有说如何识别物体是否大?

我有以下问题,

  1. 如何识别物体是否大?
  2. 堆栈的最大大小是多少?每个操作系统会有不同的堆栈大小?
  3. 我有一个包装类vector<string>。它将有大约 100 个项目。如果我将此类分配给堆栈,它会导致堆栈溢出吗?我试过这个,但效果很好。不确定我做错了什么。
4

6 回答 6

10

首先,向量(以及所有 STL 容器类)总是从堆中分配,所以您不必担心这一点。对于任何大小可变的容器,几乎不可能使用堆栈。

如果您考虑堆栈分配的工作原理(在编译时,基本上是通过为每个对象递增一个指针),那么应该清楚向量内存来自堆。

std::vector<int> myInts;
std::string myString;
SomeOther Class;

// this memory must come from the heap, there's no way it
// can now be allocated on the stack since there are other
// objects and these parameters could be variable
myString = "Some String";
myInts.reserve(256);

除非您在递归函数中,否则您可以将几千字节的数据放在堆栈上而不必担心。堆栈大小由程序(而不是操作系统)控制,默认值范围为 32kb - 1mb。大多数桌面软件都在 1mb 范围内。

单个对象几乎从来都不是问题。一般来说,它们要么对堆栈足够小,要么从堆内部分配。

如果对象是函数的本地对象,则将它们放入堆栈。如果不把它们放在堆上。

将堆用于为加载/排序/操作数据分配的大缓冲区。

于 2009-03-06T02:18:38.500 回答
4

根据MSDN堆栈大小默认为 1mb。(这显然是给 Msdev 的)。

从文章中可以看出,您可以在编译时使用 /F 标志修改堆栈大小。

我认为您关于堆栈与堆使用的第一个指南非常准确,条件是如果您的临时范围变量大于 mb,请将其粘贴在堆上(并且可能会问为什么您要在短时间内分配这么多内存首先时间)。

于 2009-03-06T02:16:34.527 回答
3

您可以在堆栈上分配大对象的唯一方法是在某些时候使用旧式数组。例如:

void f() {
   char a[1000000];    // big object on the stack
}

struct A {
   char c[1000000];
};

void g() {
   A a;      // another big object on the stack
}

如果你不使用数组(你不应该),那么大多数东西都会在堆上为你分配:

void h() {
   std::string s( 100000 );
}

上面在堆栈上为指针、大小信息等分配了几个字节,然后在堆上分配实际存储。

所以别担心了!你可能做对了!

于 2009-03-06T02:21:18.917 回答
1

如何识别物体是否大?

取决于您的编译器/平台组合。没有一个真正的限制。编译器通常允许您对此进行调整。

堆栈的最大大小是多少?每个操作系统会有不同的堆栈大小?

主要取决于上述。唯一的事情是您对调音的控制较少。

我有一个包装矢量的包装类。它将有大约 100 个项目。如果我将此类分配给堆栈,它会导致堆栈溢出吗?我试过这个,但效果很好。不确定我做错了什么。

只要此包装器和该块中其他对象的总内存需求不超过您的堆栈帧大小,就可以工作。这又取决于平均字符串 sie。

一个好主意是单步调试器并查看堆栈地址——这将在某种程度上为您提供宽度的开始。和文档。

于 2009-03-06T02:17:31.357 回答
1

还有一点我要提到的是,因为vector<>必须能够调整自身的大小,所以如果它变得足够大(见下文),它必须使用堆来存储其包含的对象,即使它vector<>本身被声明为堆栈变量。

[编辑]正如 Motti 在评论中指出的那样,有可能vector<>在其堆栈分配的对象中保留少量空间作为小向量的优化。在这种情况下,使用足够小以适合此空间的向量将不需要任何堆分配。(这个预先分配的空间必须非常小,以避免在使用较小的向量时浪费空间。)无论如何,如果向量变得足够大,它将需要在堆上(重新)分配。

于 2009-03-06T02:20:53.627 回答
1

1.如何识别物体是否大?

使用“大小”

class c {
  std::vector<std::string> s;
};

int 大小 = sizeof(c);

在我的机器上,“大小”是 16 个字节。

2. 堆栈的最大大小是多少?每个操作系统会有不同的堆栈大小?

你不能说,但它绝对不是分配大量数据的好地方。

3. 我有一个包装矢量的包装类。它将有大约 100 个项目。如果我将此类分配给堆栈,它会导致堆栈溢出吗?我试过这个,但效果很好。不确定我做错了什么。

不,std::vector 分配堆中的 100 个项目。

于 2009-03-06T06:25:41.310 回答