如何判断一个对象是否应该在堆栈上?

发布于 2024-07-14 10:18:44 字数 426 浏览 10 评论 0原文

我正在寻找在 C++ 中在堆栈或堆上分配对象的经验法则。 我在这里发现了很多关于SO的讨论。 很多人说,这关系到一个对象的生命周期。 如果您需要比函数范围更长的生命周期,请将其放入堆中。 这是完全有道理的。

但让我困惑的是,很多人说,如果对象很小,就将它们分配到堆栈。 如果对象很大,请将其放入堆中。 但他们都没有说如何辨别一个物体大还是小?

我有以下问题,

  1. 如何识别一个物体大与否?
  2. 堆栈的最大大小是多少? 每个操作系统都有不同的堆栈大小?
  3. 我有一个包装 vector 的包装类。 它将有大约 100 件物品。 如果我把这个类分配到栈上,会不会造成栈溢出? 我尝试过这个,但效果很好。 不确定我做错了什么。

I was looking for a rule of thumb for allocating objects on stack or heap in C++. I have found many discussions here on SO. Many people said, it's about the lifetime of an object. If you need more lifetime than the scope of the function, put it in the heap. That makes perfect sense.

But what made me confusing is, many people said, allocate objects to stack if they are small. If objects are big, put it to heap. But none of them said how to identify an object is big or not?

I have the following questions,

  1. How to identify an object is big or not?
  2. What will be the stack maximum size? Each OS will have different stack size?
  3. I have a wrapper class which wraps vector<string>. It will have around 100 items. Will it make a stack overflow if I allocate this class to a stack? I tried this, but it worked perfectly. Not sure I am doing something wrong.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

﹏雨一样淡蓝的深情 2024-07-21 10:18:45

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

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

One more point I'll mention is that because vector<> must be able to resize itself, if it grows large enough (see below) it must use the heap for storing its contained objects, even if the vector<> itself is declared as a stack variable.

[EDIT] As Motti points out in a comment, it's possible that vector<> reserves a small amount of space inside its stack-allocated object as an optimisation for small vectors. In that case, working with vectors small enough to fit inside this space will not require any heap allocations. (This pre-allocated space must be quite small to avoid wasting space when working with smaller vectors.) Regardless, if the vector grows sufficiently large, it will require (re-)allocation on the heap.

念三年u 2024-07-21 10:18:44

首先,向量(以及所有 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 范围内。

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

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

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

Well firstly vectors (and all the STL container classes) always allocate from the heap so you don't have to worry about that. For any container with a variable size it's pretty much impossible to use the stack.

If you think about how stack allocation works (at compile time, basically by incrementing a pointer for each object) then it should be clear that vector memory comes from the heap.

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);

Unless you are in a recursive function you can place several kilobytes of data on the stack without much worry. Stack-sizes are controlled by the program (not the OS) and the default tends to range from 32kb - 1mb. Most desktop software comes in at the 1mb range.

Individual objects are almost never a concern. In general they will either be small enough for the stack, or will allocate internally from the heap.

If objects are local to a function put them on the stack. If not put them on the heap.

Use the heap for large buffers you allocate for loading/sorting/manipulating data.

扛刀软妹 2024-07-21 10:18:44

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

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

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

According to MSDN stack size defaults to 1mb. (This is for Msdev obviously).

As you can see from the article, you can modify the stack size at compile time with the /F flag.

I think your first guideline for stack vs heap usage is pretty accurate, with the qualification that if you temporary scope variable is bigger than a mb, stick it on the heap (and probably ask why you are allocating so much memory for a short period of time in the first place).

人生百味 2024-07-21 10:18:44

在堆栈上分配大对象的唯一方法是在某个时刻涉及旧式数组。 例如:

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 );
}

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

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

The only way you can allocate large objects on the stack is to have an old-style array involved at some point. For example:

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
}

If you don't use arrays (and you shouldn't) then most things will be allocated for you on the heap:

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

the above allocates a few bytes on the stack for pointers, size info etc. and then allocates the actual storage on the heap.

So stop worrying! You are probably doing things right!

≈。彩虹 2024-07-21 10:18:44

如何判断一个物体大与否?

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

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

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

我有一个包装向量的包装类。 它将有大约 100 件物品。 如果我把这个类分配到栈上,会不会造成栈溢出? 我尝试过这个,但效果很好。 不确定我做错了什么。

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

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

How to identify an object is big or not?

Depends on your compiler/platform combo. There is no One True limit. Compilers often allow you to tune this.

What will be the stack maximum size? Each OS will have different stack size?

Depends mostly as above. Only thing you have less control of tuning.

I have a wrapper class which wraps vector. It will have around 100 items. Will it make a stack overflow if I allocate this class to a stack? I tried this, but it worked perfectly. Not sure I am doing something wrong.

Will work as long as the total memory requirement of this wrapper and other objects in that block does not exceed your stack frame size. Which in turn depends on the average string sie.

A good idea is to step through a debugger and see the stack addresses -- that'll give you a start of the width to some extent. And the documentation.

我不咬妳我踢妳 2024-07-21 10:18:44

1. 如何判断一个对象大还是小?

使用“sizeof”

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

int size = sizeof(c);

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

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

你无法判断,但这绝对不是分配大量数据的好地方。

3. 我有一个包装向量的包装类。 它将有大约 100 件物品。 如果我把这个类分配到栈上,会不会造成栈溢出? 我尝试过这个,但效果很好。 不确定我做错了什么。

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

1. How to identify an object is big or not?

Use "sizeof"

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

int size = sizeof(c);

On my machine "size" is 16 bytes.

2. What will be the stack maximum size? Each OS will have different stack size?

You can't tell, but it's definitely not a good place to allocate masses of data.

3. I have a wrapper class which wraps vector. It will have around 100 items. Will it make a stack overflow if I allocate this class to a stack? I tried this, but it worked perfectly. Not sure I am doing something wrong.

No. std::vector allocates the 100 items in the heap.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文