C++中的变量存储在哪里?
是存储在RAM还是处理器缓存中?
C++中的变量存储在哪里?
是存储在RAM还是处理器缓存中?
命名变量被存储在:
static
变量,则存储在每个进程的数据区中。section .data
、.bss
、.rodata
或类似的位置放置/保留字节来实现。如果变量是使用 int *p = new int[10];
或类似方法初始化的指针,则指针变量 p
将像上面所述一样存储在自动存储或静态存储中。内存中的指向对象为:
new
或 malloc
等分配。当然,这全部都是在RAM中的。缓存对用户空间进程透明,但它可能会影响性能。
编译器可以优化代码以将变量存储在寄存器中。这高度依赖于编译器和代码,但好的编译器会积极地这样做。
注1:有趣的事实:auto
在C++03及之前版本以及现在的C语言中表示自动存储类别,但现在(C++11)它可以推断类型。
myclass foo = { ... };
变量,因此类对象本身(以及所有成员)都在自动(堆栈)或静态存储中,而不是动态(堆)。使用动态分配的存储来存储具有命名子对象的聚合对象与使用指针将该内存作为带编号元素的数组并没有根本区别。你仍然只能通过某些指针或引用访问它。 - Peter Cordes对于C++来说,通常情况下,变量存储在编译器决定的位置。除非你指定编译器处理方式,否则不应该做出其他假设。有些变量可以完全存储在寄存器中,有些可能会被优化并替换为某个字面值。在某些平台上,一些编译器实际上可能会将常量存储在ROM中。
关于“处理器缓存”的问题有点混淆。虽然有一些工具可以指导处理器如何处理其缓存,但总体来说,这是处理器的事情,应该对用户透明。您可以将高速缓存视为CPU与RAM之间的窗口。几乎任何内存访问都通过高速缓存。
另一方面,大多数操作系统会将未使用的RAM交换到磁盘上。因此,在某些时刻,您的变量实际上可能会存储在磁盘上,但这种情况较少发生。
变量通常存储在RAM中,它们可以在堆(例如全局变量、方法/函数中的静态变量)或栈(例如在方法/函数内声明的非静态变量)上。堆和栈都是RAM,只是不同的位置。
指针有点特殊。指针本身遵循上述规则,但它们所指向的数据通常存储在堆上(使用malloc
创建的内存块或使用new
创建的对象)。但是您可以创建指向栈内存的指针:int a = 10; int * b = &a;
; b
指向a
的内存,而a
存储在栈中。
CPU缓存中放入什么超出编译器的控制范围,CPU自己决定要缓存什么以及缓存多长时间(取决于因素如“这些数据最近是否被使用过”或“预计这些数据很快会再次使用吗”),当然缓存的大小也会产生很大影响。
编译器只能决定哪些数据进入CPU寄存器。通常情况下,如果一行代码中频繁访问某个数据,则将其保存在寄存器中,因为寄存器访问速度比缓存和RAM更快。在某些系统上,某些操作只能在数据在寄存器中时才能执行,在这种情况下,编译器必须在执行操作之前将数据移动到寄存器中,并且只能在何时将数据移回RAM。
编译器始终会尝试将最常访问的数据保存在寄存器中。当调用一个方法/函数时,通常所有寄存器值都会被写回RAM,除非编译器可以肯定所调用的函数/方法不会访问内存中来自的数据。同时,在方法/函数返回时,必须将所有寄存器数据写回RAM,否则新值将会丢失。在某些CPU体系结构中,返回值本身是通过寄存器传递的,否则通过堆栈传递。
int x;
堆:
int *p = new int;
话虽如此,两者都是在RAM中构建的结构。
如果您的RAM使用率很高,Windows可以将其交换到磁盘。
当变量进行计算时,内存将被复制到寄存器中。
C++不知道你处理器的缓存。
当你运行一个用C++或其他语言编写的程序时,你的CPU会在缓存中保留“热门”的RAM块的副本。这是在硬件级别上完成的。
不要把CPU缓存看作“其他”或“更多”的内存...它只是一种将某些RAM块保持靠近的机制。
ulimit -s
设置的限制,该进程从其父进程继承,而不是由链接器设置。此外,整个大小在进程启动时技术上未映射(因此仅在/proc/self/maps
中显示出较小的初始大小),更不用说在硬件页表中固定了。但是它是保留的,因此其他映射(如mmap(MAP_ANONYMOUS)
)不会窃取它。触及堆栈指针下方的内存会触发映射的自动扩展。什么是“自动堆栈扩展”? - Peter Cordes或者,您可能需要为输入数据中的每个记录或每个定义分配一个块;由于您无法预先知道有多少个,因此必须在读取每个记录或定义时为其分配新块。
当您使用动态分配时,内存块的分配是程序明确请求的操作。您在想要分配空间时调用函数或宏,并使用参数指定大小。如果您想释放空间,则通过调用另一个函数或宏来执行此操作。您可以随时以任意频率执行这些操作。
C++变量不支持动态分配;没有存储类“dynamic”,也永远不会有C++变量的值存储在动态分配的空间中。获取动态分配的内存的唯一方法是通过系统调用,引用动态分配的空间的唯一方法是通过指针。由于它不太方便,而且实际的动态分配过程需要更多的计算时间,因此程序员通常仅在静态和自动分配都无法满足需求时才使用动态分配。
例如,如果您想动态分配一些空间来保存一个名为 foobar 的结构体,您不能声明一个类型为 struct 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中有一份副本,除非编译器决定这是不必要的。