如本教程中所述: http://www.learncpp.com/cpp-tutorial/79-the-stack-and-the-heap/
在计算机编程中,堆栈是容纳其他容器的容器 变量(很像一个数组)。但是,阵列可以让你 按您希望的任何顺序访问和修改元素,堆栈更多 有限。可以在堆栈上执行的操作是相同的 对于上面的那些:
1)查看堆栈顶部的项目(通常通过函数完成) 名为top())2)将顶部项目从堆栈中取出(通过a。完成 函数叫pop())3)在堆栈顶部放一个新项目(通过 一个叫做push()的函数
但如果我在C ++中定义了两个变量,我就不必按照相同的定义顺序使用它们了:
示例:
int main() {
int a;
int b;
b = 5;
a = 6;
}
这段代码有问题吗?我可以按照我喜欢的任何顺序使用它们!我不必首先使用 a ,然后使用 b 。
我误解了什么吗?它是什么?
答案 0 :(得分:8)
你混淆了两种不同的堆栈。
一个堆栈,用于分配应用程序的某些内存。这将是关于堆栈和堆以及分配内存的讨论的一部分。
另一种堆栈是符合LIFO访问方式的数据结构。这可以使用std :: vector或其他形式的数据结构来实现。
答案 1 :(得分:4)
是的,保存被调用方法的局部变量的“自动存储”在堆栈中分配。但是使用自动存储堆栈,您可以推送和弹出(可变大小)“堆栈帧”,其中包含方法的所有局部变量,而不是单个值。
这在概念上类似于您引用的文章中讨论的堆栈类型,只是推送和弹出的项目要大得多。
在这两种情况下,机制都是“LIFO”,因为当你调用一个方法时你实际上是通过“弹出堆栈”返回 - 你总是必须以你调用它们的相反顺序从方法返回。
答案 2 :(得分:1)
我误解了什么吗?它是什么?
你把'a'和'b'打开的“堆栈”是(警告巨大的简化和概念)不是由变量构成的;它是由堆栈框架组成的。堆栈帧由函数的参数和返回值的空间组成,有时还包括函数中使用的变量(除了这些变量也可以保存在寄存器中,有时参数也通过寄存器传递)。通过调用函数来“推送”到该堆栈上。从该堆栈“弹出”是通过从函数返回来完成的。你确实只能访问“top”元素;你不能只读取调用当前函数的函数的变量,除非它们作为参数显式传入。
答案 3 :(得分:1)
与任何其他数据结构一样,堆栈是遵循LIFO(后进先出)原则的数据结构。如您的问题所述,它根据LIFO原则进行推送和弹出操作以输入和检索数据。
每个进程基本上由4个地址空间部分组成 可以访问该过程 何时运行
文本 - 此部分包含实际的m / c指令 执行。在许多操作系统上,这被设置为只读,因此 进程无法修改其说明。这允许多个实例 分享文本单一副本的程序。
数据 - 此部分包含程序的数据部分。它更进一步 分为
1)初始化只读数据 - 包含数据元素 由程序初始化,它们只在读取期间读取 执行过程。
2)初始化读写数据 - 包含数据元素 由程序初始化并将在过程中修改 流程执行。
3)未经初始化的数据 - 这包含的元素不是 由程序初始化并在进程执行前设置为0。 这些也可以修改并称为BSS(块起始符号)。该 adv这样的元素是,系统不必分配空间 该区域的程序文件,b'coz在OS之前被OS初始化为0 过程开始执行。
Stack - 此部分用于局部变量,堆栈帧
堆 - 此部分包含动态分配的内存
int abc = 1; ----> Initialized Read-Write Data
char *str; ----> BSS
const int i = 10; -----> Initialized Read-Only Data
main()
{
int ii,a=1,b=2,c; -----> Local Variables on
Stack
char *ptr;
ptr = malloc(4); ------> Allocated Memory in Heap
c= a+b; ------> Text
}
数据,存储数据 文字,商店代码
链接器生成的文件有3个(主要?)段/部分。 text - 程序文本(显然是const char数组。也许是其他'const'数组,因为那些无论如何都无法改变)。我不是100%肯定阵列部分,也许 有人会纠正我。
数据 - 初始化的全局数据。见下面的例子。 bss - 未初始化的全球数据。 以下是一些例子
int x = 1; /* goes into data */
int y; /* goes into bss */
const int z = 1;
这个,我们已经看到进入'文本',因为无论如何都无法改变,但可以保护
const char array[] = {'a','b'....etc}
/* the rest goes into text */
int main(void)
{
return EXIT_SUCCESS;
}
符号启动阻止
(BSS)由Unix链接器生成的未初始化的数据段。其他段是包含程序代码和“数据”段包含的“文本”段 初始化数据。 bss段中的对象只有名称和大小,但没有值。
答案 4 :(得分:1)
您不必按照定义的顺序使用它们。但是它们被销毁 - 按顺序从堆栈中取出。 LIFO并不是指访问,只是将内容放在堆栈上或从堆栈中取出。
您可以通过更改int
来打印在其析构函数中的类型来轻松地观察到这一点。
答案 5 :(得分:0)
堆栈是一种在整个地方使用的标准数据结构。线程所谓的堆栈实际上是这种范例的实现。有一个堆栈指针(通常在处理器寄存器中)指向一个内存位置。通过移动sp将数据“推”到该堆栈上。我们通过返回它指向的值并将sp向相反方向移动来“弹出”。
就你的a,b声明,它没有任何区别。它们在被使用之前都被分配了。
答案 6 :(得分:0)
堆叠程序:
您的示例程序不是堆栈的实现。堆栈应存储元素,如数组(或通过某种方式),其中元素可以按LIFO(后进先出)顺序推送(存储)或加载(拉出)。它的实现并不像声明两个变量那么简单。标准C ++提供了堆栈类,因此您可以使用它而无需自己实现。
堆叠内存:
函数中的变量以LIFO顺序存储在堆栈存储器(RAM中的某处)中。从您的示例中,将创建Variable a并将其推送到堆栈内存。然后,变量b被推送到堆栈存储器。函数完成执行后,变量以LIFO方式销毁。所以变量b是第一个被破坏的,最后变量a被破坏了。你没有为它编写代码。编译器会为它编写汇编低级代码。