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

时间:2008-10-23 17:14:56

标签: c++ architecture memory computer-architecture

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

在RAM或处理器的缓存中?

9 个答案:

答案 0 :(得分:35)

存储变量:

  • 在堆栈上,如果它们是auto - matic function-local variables
  • 在堆上,如果它们被分配了newmalloc等等(在评论中说“变量存储在堆中”的含义的详细信息)
  • 在每个进程数据区域中,如果它们是全局的或static

当然,这都在RAM中。缓存对用户空间进程是透明的,但它可能会对性能产生不利影响。

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

答案 1 :(得分:16)

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

关于“处理器缓存”的问题部分有点混乱。有一些工具可以指导处理器处理缓存的方式,但一般来说这是处理器的业务,应该对您不可见。您可以将缓存视为CPU进入RAM的窗口。几乎任何内存访问都通过缓存。

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

答案 2 :(得分:8)

变量通常存储在RAM中。这可以在堆上(例如,所有全局变量通常都会在那里)或在堆栈上(在方法/函数中声明的所有变量通常都在那里)。堆栈和堆都是RAM,只是不同的位置。指针有不同的规则。指向某事物(内存块,对象等)本身的指针通常遵循上面的规则(在函数中声明的指针存储在堆栈中),但它指向的数据(内存块本身或对象)你用new创建的)存储在堆上。您可以创建指向堆栈的指针(例如“int a = 10; int * b =& a;”,b指向a,a存储在堆栈中),但使用malloc或new计数内存分配给堆内存

进入CPU缓存的内容超出了编译器的控制范围,CPU决定自己要缓存什么以及如何长时间缓存它(取决于“最近是否使用过此数据?”或“是否预期到数据很快就会被使用?“当然,缓存的大小对CPU将数据保存多久有很大影响 - 它们拥有的缓存越多,它们可以缓存的数据就越多,它们之前保存数据的时间就越长释放新数据的缓存空间。)

编译器可能只决定数据是否进入CPU寄存器。如果连续访问数据,通常会将数据保留在那里(因为寄存器访问比缓存更快,而且比RAM快得多)。某些系统上的某些操作实际上只能在数据位于寄存器中时执行 - 但编译器将决定是否在对其执行操作后立即将数据复制回RAM,或者将其保留在那里以对其执行更多操作在将其写回RAM之前。如果可能的话,它总会尝试将最常访问的数据保存在寄存器中,如果寄存器用完了(取决于你的CPU有多少个寄存器),它将决定是否最好将数据写回RAM(并获取)它从那里再次需要),或者只是暂时将数据交换到堆栈上,然后再从那里取回(即使堆栈也是RAM,通常使用堆栈更快,因为CPU通常有堆栈顶部缓存,无论如何因此,从堆栈推送和弹出可能实际上只是写入缓存并从那里读回,数据可能永远不会到达内存。然而,当代码流从一个方法/函数跳转到另一个方法/函数时,通常所有寄存器都被写回内存,因为编译器很难确定被调用的函数/方法不会访问寄存器数据来自的存储器以及何时如果没有写回数据,该函数可能会看到内存中仍然存在一个旧值,因为新值仅存在于寄存器中且尚未写回。

答案 3 :(得分:6)

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

堆栈:

int x;

堆:

int *p = new int;

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

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

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

答案 4 :(得分:6)

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

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

不要将CPU缓存视为“其他”或“更多”内存......它只是一种机制,可以将一些RAM保存在附近。

答案 5 :(得分:4)

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

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

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

答案 6 :(得分:1)

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

如果您有任何中途优化编译器,则局部变量通常会存储在处理器的寄存器文件中。变量在读取和写入时会在RAM,缓存和寄存器文件之间来回移动,但它们通常总是在RAM / ROM中有一个副本,除非编译器认为没有必要。

答案 7 :(得分:1)

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

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

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

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

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

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

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

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

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

答案 8 :(得分:0)

取决于它们的声明方式,它们将存储在“heap”或“stack

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

当应用程序使用数据时,它必须在消耗之前移动到CPU的寄存器,但这是非常不稳定和临时存储。