【问题标题】:Is this nested array using stack or heap memory?这个嵌套数组是使用堆栈还是堆内存?
【发布时间】:2011-11-08 01:45:09
【问题描述】:

假设我有这个声明并使用嵌套在向量中的数组

const int MAX_LEN = 1024;
typedef std::tr1::array<char, MAX_LEN> Sentence;
typedef std::vector<Sentence> Paragraph;

Paragraph para(256);
std::vector<Paragraph> book(2000);

我假设Sentence 的内存在堆栈上。
对吗? 向量para 的内存呢?那是在堆栈上吗,即我是否应该担心我的 para 太大了?
最后,书的记忆呢?我猜这必须在堆上,但嵌套数组在堆栈上,不是吗?
其他问题
Paragraph 的内存是否连续?
book 的内存是连续的吗?

【问题讨论】:

标签: c++


【解决方案1】:

没有堆栈。 不要考虑堆栈。重要的是给定的容器类是否执行任何动态分配。

std::array&lt;T,N&gt; 不使用任何动态分配,它是一个自动分配的T[N] 的包装器。

您放入向量中的任何内容由向量自己的分配器分配,在默认情况下(通常)使用::operator new() 执行动态分配。

简而言之,vector&lt;array&lt;char,N&gt;&gt;vector&lt;int&gt; 非常相似:分配器只是为array&lt;char,N&gt;(或int)的单元分配内存,因为它需要在该内存中保存和构造元素。冲洗并重复嵌套向量。


对于您的“其他问题”:vector&lt;vector&lt;T&gt;&gt; 绝对与 T 不连续。对于vector&lt;T&gt;,它只是连续的,但 only 包含内部向量的小簿记部分。内部向量的实际内容由内部向量的分配器分配,并且为每个内部向量单独分配。通常,vector&lt;S&gt;S 类型是连续的,仅此而已。

我实际上不确定vector&lt;array&lt;U,N&gt;&gt; -- 它可能 对于U 是连续的,因为除了包含的U[N] 之外,该数组没有理由包含任何数据,但我'不确定这是否是强制性的。

您可能想将其作为一个单独的问题提出,这是一个很好的问题!

【讨论】:

  • -1 “没有堆栈”是不正确的(关于 C++ 必须支持什么系统的都市神话)。请不要传播愚蠢的城市神话。这让初学者很难理解诸如“stack unwinding”之类的标准术语——如果不存在,就有点难以解开。
  • @Alf:我认为那里的标准措辞很糟糕。它不是真正的“堆栈展开”而是“范围展开”,我们只是使用这个术语,因为它让初学者很容易理解。正如技术上不需要堆栈一样,它只是最简单的方法(也是实现它的唯一真正实用的方法(尽管它可以通过其他方式完成(60 年代的历史和俄罗斯编译器已经表明)(他们生成了自我修改的代码)). 堆栈的概念并不能帮助初学者理解 C++(我个人认为它更难)尤其是对于这个问题的答案。
  • 用自动和动态存储持续时间对象和范围来解释问题要容易得多。这也是用标准来解释的正确方式。所以我必须同意:就像“没有勺子”一样,这只是一种简单的方式来感知某些概念,而不是变量及其寿命。 (是的,我的意思是勺子,因为总会有一堆它只是不相关的)。
  • @Alf:我不是想喷人,我只是不同意你的观点。我目前正在寻找标准来证明自己是错误的。
  • @Alf:我知道我很吝啬,通常从堆栈的角度来考虑是完全可以的。但是对于这个问题,我真的认为这是思考问题的错误方式——最初的问题“是堆栈上的数组”已经以错误的方式处理它,尤其是与“数组容器去哪里”配对”。从自动与动态存储和分配器的角度来考虑它会更清晰,它可以让大脑从与概念无关的不必要的混乱和细节中解放出来。
【解决方案2】:

您的代码示例:

const int MAX_LEN = 1024;
typedef std::tr1::array<char, MAX_LEN> Sentence;
typedef std::vector<Sentence> Paragraph;

Paragraph para(256);
std::vector<Paragraph> book(2000);

“我假设 Sentence 的内存在堆栈上。对吗?” 没有。是否在堆栈上分配了某些内容取决于声明上下文。您省略了上下文,因此无话可说。如果一个对象是本地的且非静态的,那么您将获得对象本身的堆栈分配,但不一定适用于它在内部引用的部分。顺便说一句,由于这里的另一个答案声称“没有堆栈”,所以请忽略关于 C++ 必须支持哪种系统的都市传说。它最初源于对一个相当不成功的硬件级别优化计算机如何工作的误解,一些人错误地认为它没有简单的硬件支持的类似数组的堆栈实现。从“不简单”到“不存在”是相当长的一段,甚至“不简单”也是完全错误的,不仅在事实上而且在逻辑上(最终自相矛盾)。 IE。这是一个不太聪明的初学者的错误,尽管这个神话已经被至少一个有经验的人传播了。无论如何,C++ 保证了一个抽象堆栈,并且在所有现有的计算机上,保证抽象堆栈是根据硬件辅助的类似数组的简单堆栈实现的

“vector para 的内存呢?在栈上吗” 同样,这取决于您没有显示的声明上下文。同样,即使对象本身是在堆栈上分配的,它在内部引用的部分也不会(通常)在堆栈上分配。

“也就是说,如果我的 para 太大,我应该担心吗?” 不,不用担心。 std::vector 动态分配其缓冲区。它不受可用堆栈空间的限制。

“最后,书的内存呢?我猜它必须在堆上,但嵌套数组在堆栈上,不是吗?” 没有也没有。

“Paragraph 的内存是否连续?” 没有。但是向量的缓冲区是连续的。这是因为std::array 保证是连续的,而std::vector 的缓冲区保证是连续的。

“书的内存是连续的吗?” 没有。

【讨论】:

  • @anonymous downvoter:请说明您投反对票的原因,以便其他人可以从您的见解中受益,呵呵。''
  • 好吧,现在挑剔,但我认为理解 C++ 的哲学很重要:“向量动态分配其缓冲区”当然是正确的,但与有限堆栈没有直接关系空间——真实的是malloc() 不依赖于堆栈大小。但是我可以为我的向量编写一个分配器,它确实从我在声明向量之前放在堆栈上的内存缓冲区分配。它是人为的,但它显示了语言的灵活性,以及​​任何给定的预设可能无法解释所有情况。
  • @All:我不确定您对 Paragraph 记忆连续性的回答在实际中意味着什么。内存不是连续的,但缓冲区是连续的?
  • @matias: std::vector 是一个固定大小的小对象,它包含(以及其他可能的东西)指向缓冲区的指针,该缓冲区驻留在内存中的其他位置。画那个。然后考虑一个向量的向量。包含的向量对象驻留在外部向量的缓冲区中。它们中的每一个都包含一个指向它自己的缓冲区的指针。画那个。
【解决方案3】:

附带说明,使用gdb 可能会有所帮助。它使您可以手动检查您的记忆,包括变量的位置。您可以准确地检查自己正在使用的内存。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-27
    • 1970-01-01
    • 2021-06-19
    • 1970-01-01
    • 2015-05-03
    • 2020-01-10
    相关资源
    最近更新 更多