22

C++ 标准没有提到堆栈或堆的任何内容,它们是特定于实现的,这是真的。

尽管它们不是 C++ 标准的一部分,但我们最终还是会使用它们,以至于它们就像是语言本身的一部分,并且必须考虑到内存或性能目的。

因此我的问题是有不使用堆栈和堆的 C++ 实现吗?

4

7 回答 7

12

其他人已经对堆给出了很好的答案,所以我将不理会它。

一些实现(例如,在 IBM 大型机上)不像大多数人所想的那样使用堆栈,原因很简单,硬件不支持它。相反,当您调用函数时,会从堆(它们的版本)分配激活记录(即,用于本地、参数和返回地址的空间)。这些激活记录被构建到一个链表中。

从纯粹抽象的角度来看,这肯定是一个堆栈——它支持后进先出语义,就像任何其他堆栈一样。不过,您确实必须非常抽象地看待它才能将其称为堆栈。如果您向人们展示链接在一起的内存块的图表,我认为可以肯定地猜测大多数程序员会将其描述为链表。如果你推送它们,我想大多数人会这样判断它“是的,你可以以类似堆栈的方式使用它,但它仍然是一个链表”。

于 2012-06-05T19:49:27.400 回答
6

C++ 标准没有提及堆栈或堆的任何内容

它实际上是——只是不是用这些话,也没有指定堆栈和堆是如何实现的。

在 C++03 中有三种变量:

  1. 具有静态存储持续时间的那些(3.7.1)。这些在计划期间是“范围内”的。
  2. 具有自动存储期限的那些(3.7.2)。这些仅在声明它们的上下文中才在范围内。一旦它们超出范围,变量就会被销毁并释放。
  3. 具有动态存储期限的那些(3.7.3)。这些是用new表达式创建的,并用delete. 对象本身是无范围的,因为它们的生命周期不受new编辑它们的上下文的约束。指向这些对象的立即指针当然是有作用域的。指针是自动的,或者很少(通常是错误的)静态存储持续时间。

“堆栈”和“堆”实际上只是后两种类型的对象所在的位置。它们是实现语言要求的平台相关实现细节。

所以,从技术上讲,你是对的。该标准没有说明堆和堆栈。但它确实说了很多关于不同风格的存储持续时间,这需要在真实平台上进行某种实现在大多数现代 PC 类型的硬件上,这被实现为堆和堆栈。是否可以在不使用堆或堆栈的情况下在平台上实现不同类型的存储持续时间?一切皆有可能——我想它可以。但无论该实现最终是什么,它都可能具有至少与两者之一相似的特征。

除此之外,还需要考虑标准要求自动和动态存储持续时间。不满足这两个要求的任何语言实现都不是 C++。它可能很接近,但它不会真的是 C++。

于 2012-06-05T16:39:47.683 回答
4

对于小型编程环境,例如基于 8K Atmel 微处理器(现在它有 32K 或更多)的arduino 平台,没有实现堆,也没有库定义的新运算符。所有对象都是静态创建或在堆栈上创建的。您失去了标准库的优势,但获得了能够使用面向对象的语言来编写一个非常小的平台 - 例如,创建类来表示配置为特定输出模式或串行端口的引脚,创建该类的对象给它引脚号,然后调用该对象上的函数,而不必将引脚号传递给您的例程。

如果您new在 arduino 上使用,您的程序会编译但不会链接 - 编译器是针对 avr 指令集的 g++,所以是真正的 C++ 编译器。如果您选择提供自己的实现,则可以这样做,但在大多数情况下,在如此小的空间内提供实现的成本并不值得。

于 2012-06-05T16:41:56.770 回答
1

这基本上是在回应 TA 先生的回答(+1 BTW)。栈和堆是抽象概念。

newanddelete运算符(andmallocfree函数)实际上只是称为堆的抽象的接口。因此,当您要求 C++ 实现“无堆”时,您实际上是在要求实现不允许您使用这些接口。我认为没有什么可以阻止实现总是使这些接口失败。

调用函数并在调用返回后恢复当前执行(以及可选地检索返回值)是堆栈抽象的接口。当您要求 C++ 实现“无堆栈”时,您要求 C++ 实现禁止程序执行这些操作。我想不出一种让编译器强加这种条件的合规方式。语言规定允许源代码定义函数,并定义代码来调用函数。

所以我的回答是:“无堆栈”不,“无堆”是的。

于 2012-06-05T16:57:00.780 回答
1

是的,主要是像飞思卡尔和PIC这样的MCU

2. 现在正在使用无堆栈处理器。

我们不像汇编程序员那样看待内核。只要存在所需的基础知识,我们就对基本程序员的模型感到满意。堆栈不是其中之一:我们最近遇到了几个无堆栈内核,并且为它们开发 C 编译器没有问题。

eTPU 是一个 24 位增强型时间处理单元,用于汽车和通用航空发动机控制以及过程控制。eTPU 可能是一个协处理器,但它有完整的指令集和完整的 CPU 内核,而且它是无堆栈的。它是一款中等容量的处理器:今晚你可能会开车或飞回家,这要归功于无堆栈处理器上的 C。

我们有一个基于 C99 和 ISO/IEC 18037 的 eTPU 的 C 编译器。我们在这个处理器上运行标准的 C 测试套件。

飞思卡尔 RS08 是一种更传统的无堆栈 MCU。在“减少”HC08/HCS08内核的过程中,飞思卡尔移除了CPU堆栈。我们咨询了 RS08 的架构,从没觉得有必要坚持硬件栈。

提到我们咨询过的另一个协处理器,飞思卡尔 XGATE 有一个非常友好的 ISA 和程序员模型,但它没有堆栈。

然后是“几乎无堆栈”。Microchip PIC 从来没有数据堆栈,只有一个 8 入口(或增强型 14 位内核中的 16 入口)调用返回堆栈。没有人怀疑 C 可用于 PIC。

这些部分,尤其是 eTPU,被设计为对编译器友好并鼓励机器生成代码。

还有其他基于非堆栈的处理器,其中一些是最近创建的,涵盖一系列应用程序并享受自己的 C 编译器。有中到大批量的无堆叠零件。性能通常是零件没有堆栈的主要原因。

http://www.bytecraft.com/Stack_controversy

于 2018-01-16T12:58:14.267 回答
0

由于 C++ 定义了诸如函数和 new 运算符之类的构造,因此不可能有无堆栈和无堆的实现。调用函数需要一个堆栈,而“新建”一个实例需要一个堆。这些实现方式在平台之间可能有所不同,但想法是相同的。总是需要有一个用于实例对象的内存区域,以及另一个用于跟踪执行点和调用层次结构的内存区域。

由于 x86(和 x64)对这些东西有方便的设施(即 ESP 寄存器),编译器使用它。其他平台可能不同,但最终结果在逻辑上是等效的。

于 2012-06-05T16:17:31.510 回答
0

我敢说没有这样的 C++ 实现,只是因为堆栈和堆是非常有用的抽象,基本上市场上的所有处理器都提供了一些硬件支持以使其非常高效。

由于 C++ 以效率为目标,因此 C++ 实现将利用它们。此外,C++ 程序通常不会在真空中运行。它们必须集成到由平台的应用程序二进制接口定义的平台生态系统中。ABI - 出于同样的原因 - 定义了 C++ 实现需要遵守的堆栈和其他内存结构。

然而,让我们假设您的 C++ 程序是针对一个简单、小型、资源受限的嵌入式平台,它有一个奇异的微控制器,没有操作系统(您的应用程序将是操作系统!),没有线程或进程。

首先,平台可能根本不提供动态内存。您将需要使用在链接时定义的静态内存池,并开发自己的内存分配管理器 ( new)。C++ 允许它,并且在某些环境中确实使用它。

此外,CPU 可能使得堆栈抽象不是那么有用,因此不值得实现。例如,像 SPARC 这样的 CPU 定义了一种滑动寄存器窗口机制- 结合大量寄存器 - 使用堆栈对函数调用效率不高(如果你看一下,堆栈已经在硬件中完成了!)。

长话短说,所有 C++ 实现都使用堆栈,大多数使用堆,但原因与平台属性密切相关。

于 2012-06-05T16:50:21.123 回答