繁体   English   中英

C++中的变量存储在哪里?

[英]Where are variables in C++ stored?

C++中的变量存储在哪里?

在 RAM 或处理器的缓存中?

命名变量存储:

  • 在堆栈上,如果它们是函数局部变量。
    C++ 称这种“自动存储”为1并且不要求它实际上是 asm 调用堆栈,在一些罕见的实现中它不是。 但在主流实现中确实如此。
  • 在每个进程的数据区域中,如果它们是 global 或static
    C++ 称之为“静态存储类”; 它通过在section .data.bss.rodata或类似section .data放置/保留字节在 asm 中实现。

如果变量是一个用int *p = new int[10];初始化的指针int *p = new int[10]; 或类似的,指针变量p将进入自动存储或静态存储,如上所述。 内存中指向的对象是:

  • 在堆上(C++ 称之为动态存储),用newmalloc等分配。
    在 asm 中,这意味着调用分配器函数,如果其空闲列表为空,则该函数最终可能会通过某种系统调用从操作系统获取新内存。 “堆”不是现代操作系统/C++ 实现中的单个连续区域。

C 和 C++ 不进行自动垃圾收集,命名变量本身不能处于动态存储(“堆”)中。 动态存储中的对象是匿名的,除了被其他对象指向之外,其中一些可能是适当的变量。 (结构或类类型的对象,与像int这样的原始类型相反,可以让你引用这个匿名对象中的命名类成员。在成员函数中,它们甚至看起来是相同的。)

这就是为什么您不能(安全/有用地)返回指向局部变量的指针或引用的原因。


当然,这一切都在 RAM 中 缓存对用户空间进程是透明的,尽管它可能会明显影响性能。

编译器可以优化代码以将变量存储在寄存器中。 这是高度依赖于编译器和代码的,但好的编译器会积极地这样做。


脚注 1:有趣的事实: auto在 C++03 及更早版本中,并且仍然在 C 中,表示自动 storage-class ,但现在 (C++11) 它推断类型。

一般来说,对于 C++,正确的答案是“无论你的编译器决定把它们放在哪里”。 您不应该以其他方式做出假设,除非您以其他方式指导编译器。 有些变量可以完全存储在寄存器中,有些变量可能会被完全优化掉并在某处替换为文字。 对于某些平台上的某些编译器,常量实际上可能最终出现在 ROM 中。

您关于“处理器缓存”的问题的一部分有点困惑。 有一些工具可以指导处理器如何处理其缓存,但通常这是处理器的业务,您应该看不到。 您可以将缓存视为 CPU 进入 RAM 的窗口。 几乎任何内存访问都通过缓存。

另一方面,在大多数操作系统上,未使用的 RAM 有时会被换出到磁盘。 因此,在某些时候您的变量实际上可能(但不太可能)存储在磁盘上。 :-)

变量通常存储在 RAM 中。 这是在堆上(例如全局变量、方法/函数中的静态变量)或堆栈上(例如在方法/函数中声明的非静态变量)。 堆栈和堆都是 RAM,只是位置不同。

指针有点特殊。 指针本身遵循上述规则,但它们指向的数据通常存储在堆上(用malloc创建的内存块,用new创建的对象)。 但是您可以创建指向堆栈内存的指针: int a = 10; int * b = &a; int a = 10; int * b = &a; ; b指向的存储器aa被存储在堆栈中。

进入 CPU 缓存的内容超出了编译器的控制,CPU 自行决定缓存什么以及缓存它的时间长短(取决于诸如“此数据最近是否被使用过? ”或“是否预期使用该数据?很快又回来了? ”)当然缓存的大小也有很大的影响。

编译器只能决定哪些数据进入 CPU 寄存器。 如果连续频繁访问数据,通常数据会保存在那里,因为寄存器访问速度比缓存快,比 RAM 快得多。 某些系统上的某些操作实际上只能在数据位于寄存器中时才能执行,在这种情况下,编译器必须在执行操作之前将数据移至寄存器,并且只能决定何时将数据移回 RAM。

编译器将始终尝试将最常访问的数据保存在寄存器中。 当一个方法/函数被调用时,通常所有的寄存器值都会被写回 RAM,除非编译器可以确定被调用的函数/方法不会访问数据来自的内存。 同样在方法/函数返回时,它必须将所有寄存器数据写回 RAM,否则新值将丢失。 在某些 CPU 架构上,返回值本身在寄存器中传递,否则通过堆栈传递。

C++ 中的变量存储在堆栈或堆中。

堆:

int x;

堆:

int *p = new int;

话虽如此,两者都是内置于 RAM 中的结构。

如果您的 RAM 使用率很高,尽管 Windows 可以将其交换到磁盘。

当对变量进行计算时,内存将被复制到寄存器。

C++ 不知道您的处理器的缓存。

当您运行用 C++ 或任何其他语言编写的程序时,您的 CPU 将在缓存中保留一份“流行”RAM 块的副本。 这是在硬件级别完成的。

不要将 CPU 缓存视为“其他”或“更多”内存……它只是一种将一些 RAM 块保持在附近的机制。

我认为您混淆了两个概念。 一、C++语言如何在内存中存储变量。 二,计算机和操作系统如何管理该内存。

在 C++ 中,变量可以在堆栈上分配,堆栈是为程序使用而保留的内存,在线程启动时大小固定,或者在动态内存中,可以使用 new 动态分配。 如果代码分析允许,编译器还可以选择将变量存储在处理器的寄存器中。 这些变量永远不会看到系统内存。

如果变量在内存中结束,操作系统和处理器芯片组接管。 基于堆栈的地址和动态地址都是虚拟的。 这意味着它们可能会或可能不会在任何给定时间驻留在系统内存中。 in memory 变量可以存储在系统内存中,分页到磁盘上,或者可以驻留在处理器上或附近的缓存中。 因此,很难知道这些数据实际上在哪里。 如果一个程序有一段时间没有空闲或两个程序正在争夺内存资源,则可以将该值保存在页面文件中的磁盘中,并在程序运行时恢复。 如果该变量是正在完成的某些工作的本地变量,则可以在处理器缓存中对其进行多次修改,然后最终将其刷新回系统内存。 您编写的代码永远不会知道发生了这种情况。 它只知道它有一个地址可以操作,所有其他系统负责其余的工作。

C++ 语言支持通过 C++ 程序中的变量进行两种内存分配:

静态分配是当您声明静态或全局变量时发生的情况。 每个静态或全局变量定义一个固定大小的空间块。 该空间在您的程序启动时(exec 操作的一部分)分配一次,并且永远不会被释放。 当您声明一个自动变量(例如函数参数或局部变量)时,就会发生自动分配。 自动变量的空间在包含声明的复合语句进入时分配,并在复合语句退出时释放。 自动存储的大小可以是变化的表达式。 在其他 CPP 实现中,它必须是一个常量。 C++ 变量不支持第三种重要的内存分配,动态分配,但可用的库函数。 动态内存分配

动态内存分配是一种技术,其中程序在运行时确定存储某些信息的位置。 当您需要的内存量或您继续需要多长时间取决于程序运行之前未知的因素时,您需要动态分配。

例如,您可能需要一个块来存储从输入文件中读取的行; 由于对一行的长度没有限制,因此您必须动态分配内存并在您阅读更多行时动态地使其变大。

或者,您可能需要为输入数据中的每个记录或每个定义一个块; 由于您无法预先知道会有多少,您必须在阅读时为每个记录或定义分配一个新块。

使用动态分配时,内存块的分配是程序显式请求的操作。 当您想分配空间时调用函数或宏,并用参数指定大小。 如果你想释放空间,你可以通过调用另一个函数或宏来实现。 你可以随时随地做这些事情。

CPP 变量不支持动态分配; 没有“动态”存储类,永远不可能有一个 CPP 变量的值存储在动态分配的空间中。 获得动态分配内存的唯一方法是通过系统调用,而引用动态分配空间的唯一方法是通过指针。 因为不太方便,而且动态分配的实际过程需要更多的计算时间,所以程序员一般只有在静态分配和自动分配都不会服务的情况下才使用动态分配。

例如,如果要动态分配一些空间来保存结构体 foobar,则不能声明内容为动态分配空间的结构体 foobar 类型的变量。 但是您可以声明一个指针类型的变量 struct foobar * 并为其分配空间的地址。 然后你可以在这个指针变量上使用运算符 '*' 和 '->' 来引用空间的内容:

 {
   struct foobar *ptr
      = (struct foobar *) malloc (sizeof (struct foobar));
   ptr->name = x;
   ptr->next = current_foobar;
   current_foobar = ptr;
 }

变量可以保存在许多不同的地方,有时在多个地方。 加载程序时,大多数变量都放在 RAM 中; 有时声明为const变量被放置在 ROM 中。 每当访问变量时,如果它不在处理器的高速缓存中,就会导致高速缓存未命中,并且处理器将在变量从 RAM/ROM 复制到高速缓存时停顿。

如果您有任何不错的优化编译器,则局部变量通常会存储在处理器的寄存器文件中。 变量将在读取和写入时在 RAM、缓存和寄存器文件之间来回移动,但它们通常始终在 RAM/ROM 中具有副本,除非编译器决定不需要这样做。

根据它们的声明方式,它们将存储在“”或“堆栈”中

堆是应用程序可以使用的动态数据结构。

当应用程序使用数据时,必须在它们被消耗之前将其移动到 CPU 的寄存器,但是这是非常易失的临时存储。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM