C++中的变量存储在哪里?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/230584/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Where are variables in C++ stored?
提问by T.E.D.
Where are variables in C++ stored?
C++中的变量存储在哪里?
Inside the RAM or the processor's cache?
在 RAM 或处理器的缓存中?
回答by Dan Lenski
Variables are stored:
存储变量:
- on the stack, if they're
auto
-matic function-local variables - on the heap, if they're allocated with
new
ormalloc
, etc. (details of what it means to say "a variable is stored in the heap" in the comments) - in a per-process data area if they are global or
static
- 在堆栈上,如果它们是
auto
-matic 函数局部变量 - 在堆上,如果它们是用
new
或malloc
等分配的(注释中说“变量存储在堆中”的含义的详细信息) - 在每个进程的数据区域中,如果它们是全局的或
static
This is all in RAM, of course. Caching is transparent to userspace processes, though it may visibily affect performance.
当然,这一切都在 RAM 中。缓存对用户空间进程是透明的,尽管它可能会明显地影响性能。
Compilers may optimize code to store variables in registers. This is highly compiler and code-dependent, but good compilers will do so aggressively.
编译器可以优化代码以将变量存储在寄存器中。这是高度依赖于编译器和代码的,但好的编译器会积极地这样做。
回答by T.E.D.
For C++ in general, the proper answer is "wherever your compiler decides to put them". You should not make assumptions otherwise, unless you somehow direct your compiler otherwise. Some variables can be stored entirely in registers, and some might be totally optimized away and replaced by a literal somewhere. With some compilers on some platforms, constants might actually end up in ROM.
一般来说,对于 C++,正确的答案是“无论你的编译器决定把它们放在哪里”。您不应该以其他方式做出假设,除非您以其他方式指导编译器。有些变量可以完全存储在寄存器中,有些变量可能会被完全优化掉并在某处替换为文字。对于某些平台上的某些编译器,常量实际上可能最终出现在 ROM 中。
The part of your question about "the processor's cache" is a bit confused. There are some tools for directing how the processor handles its cache, but in general that is the processor's business and should be invisible to you. You can think of the cache as your CPU's window into RAM. Pretty much anymemory access goes through the cache.
您关于“处理器缓存”的问题的一部分有点困惑。有一些工具可以指导处理器如何处理其缓存,但通常这是处理器的业务,您应该看不到。您可以将缓存视为 CPU 进入 RAM 的窗口。几乎任何内存访问都通过缓存。
On the other end of the equation, unused RAM sometimes will get swapped out to disk on most OSes. So its possible (but unlikely) that at some moments your variables are actually being stored on disk. :-)
另一方面,在大多数操作系统上,未使用的 RAM 有时会被换出到磁盘。因此,在某些时候您的变量实际上可能(但不太可能)存储在磁盘上。:-)
回答by Mecki
Variables are usually stored in RAM. This is either on the heap (e.g. all global variables will usually go there) or on the stack (all variables declared within a method/function usually go there). Stack and Heap are both RAM, just different locations. Pointers have different rules. The pointer to something (a memory block, an object, etc.) itself usually follows the rules of above (a pointer declared within a function is stored on the stack), but the data it points to (the memory block itself or the object you created with new) is stored on the heap. You can create pointers pointing to the stack (e.g. "int a = 10; int * b = &a;", b points to a and a is stored on the stack), but memory allocation using malloc or new counts towards heap memory.
变量通常存储在 RAM 中。这要么在堆上(例如,所有全局变量通常都在那里)或在堆栈上(方法/函数中声明的所有变量通常都在那里)。堆栈和堆都是 RAM,只是位置不同。指针有不同的规则。指向某物(内存块、对象等)本身的指针通常遵循上述规则(在函数内声明的指针存储在堆栈中),但它指向的数据(内存块本身或对象你用 new 创建的) 存储在堆上。您可以创建指向堆栈的指针(例如,“int a = 10; int * b = &a;”,b 指向 a 并且 a 存储在堆栈中),但使用 malloc 或 new 分配的内存计入堆内存。
What goes into CPU cache is beyond compilers control, the CPU decides itself what to cache and how to long to cache it (depending on factors like "Has this data been recently used?" or "Is it to be expected that the data is used pretty soon again?" and of course the size of the cache has a big influence for how long CPUs will keep data there - the more cache they have, the more data they can cache and the longer they can keep data there before freeing up cache space for new data).
进入 CPU 缓存的内容超出了编译器的控制,CPU 自行决定缓存什么以及缓存多长时间(取决于诸如“这些数据最近是否被使用过?”或“数据是否被使用过?”很快吗?”当然,缓存的大小对 CPU 将数据保存在那里的时间有很大影响——它们拥有的缓存越多,它们可以缓存的数据就越多,并且在释放缓存之前它们可以在那里保存数据的时间越长新数据的空间)。
The compiler might only decide if data goes into a CPU register. Usually data is kept there if it's accessed very often in a row (since register access is faster than cache and much faster than RAM). Some operations on some systems can actually only be performed if the data is in a register - however the compiler will decide whether to copy the data back to RAM immediately after performing an operation on it or to keep it there to perform many more operations on it before writing it back to RAM. It will always try to keep the most often accessed data in a register if possible and if it runs out of registers (depending on how many registers your CPU has), it will decide if it's better to write the data back to RAM (and fetch it from there when needed again), or just temporarily swap the data onto stack and later on fetch it back from there (even though stack is RAM as well, usually using the stack is faster since CPUs usually have the top of stack cached anyway, so pushing to and popping from stack might in fact be only writing to cache and reading back from there, the data might never arrive at memory at all). However when code flow jumps from one method/function to another one, usually all registers are written back to memory, as the compiler can hardly say for sure that the called function/method will not access the memory where the register data came from and when not writing the data back, the function might see an old value still present in memory, as the new value is only in a register and has not been written back yet.
编译器可能只决定数据是否进入 CPU 寄存器。如果数据在一行中经常被访问(因为寄存器访问比缓存快,比 RAM 快得多),通常数据会保存在那里。某些系统上的某些操作实际上只能在数据位于寄存器中时才能执行 - 但是编译器将决定是在对其执行操作后立即将数据复制回 RAM 还是将其保留在那里以对其执行更多操作在将其写回 RAM 之前。如果可能,它将始终尝试将最常访问的数据保留在寄存器中,并且如果寄存器用完(取决于您的 CPU 有多少寄存器),它将决定是否将数据写回 RAM(并获取再次需要时从那里开始),或者只是暂时将数据交换到堆栈上,然后再从那里取回(即使堆栈也是 RAM,通常使用堆栈会更快,因为无论如何 CPU 通常都会缓存堆栈的顶部,因此推入和弹出堆栈可能实际上只是写入缓存并从那里读回,数据可能永远不会到达内存)。然而,当代码流从一个方法/函数跳转到另一个方法/函数时,通常所有寄存器都会写回内存,因为编译器很难确定被调用的函数/方法不会访问寄存器数据来自的内存以及何时不写回数据,函数可能会看到内存中仍然存在旧值,因为新值仅在寄存器中并且尚未写回。通常使用堆栈会更快,因为 CPU 通常会缓存堆栈的顶部,因此推入和从堆栈中弹出实际上可能只是写入缓存并从那里读回,数据可能永远不会到达内存)。然而,当代码流从一个方法/函数跳转到另一个方法/函数时,通常所有寄存器都会写回内存,因为编译器很难确定被调用的函数/方法不会访问寄存器数据来自的内存以及何时不写回数据,函数可能会看到内存中仍然存在旧值,因为新值仅在寄存器中并且尚未写回。通常使用堆栈会更快,因为 CPU 通常会缓存堆栈的顶部,因此推入和从堆栈中弹出实际上可能只是写入缓存并从那里读回,数据可能永远不会到达内存)。然而,当代码流从一个方法/函数跳转到另一个方法/函数时,通常所有寄存器都会写回内存,因为编译器很难确定被调用的函数/方法不会访问寄存器数据来自的内存以及何时不写回数据,函数可能会看到内存中仍然存在旧值,因为新值仅在寄存器中并且尚未写回。数据可能永远不会到达内存)。然而,当代码流从一个方法/函数跳转到另一个方法/函数时,通常所有寄存器都会写回内存,因为编译器很难确定被调用的函数/方法不会访问寄存器数据来自的内存以及何时不写回数据,函数可能会看到内存中仍然存在旧值,因为新值仅在寄存器中并且尚未写回。数据可能永远不会到达内存)。然而,当代码流从一个方法/函数跳转到另一个方法/函数时,通常所有寄存器都会写回内存,因为编译器很难确定被调用的函数/方法不会访问寄存器数据来自的内存以及何时不写回数据,函数可能会看到内存中仍然存在旧值,因为新值仅在寄存器中并且尚未写回。
回答by Brian R. Bondy
Variables in C++ are stored either on the stack or the heap.
C++ 中的变量存储在堆栈或堆中。
stack:
堆:
int x;
heap:
堆:
int *p = new int;
That being said, both are structures built in RAM.
话虽如此,两者都是内置于 RAM 中的结构。
If your RAM usage is high though windows can swap this out to disk.
如果您的 RAM 使用率很高,尽管 Windows 可以将其交换到磁盘。
When computation is done on variables, the memory will be copied to registers.
当对变量进行计算时,内存将被复制到寄存器。
回答by Drew Dormann
C++ is not aware of your processor's cache.
C++ 不知道您的处理器的缓存。
When you are running a program, written in C++ or any other language, your CPU will keep a copy of "popular" chunks of RAM in a cache. That's done at the hardware level.
当您运行用 C++ 或任何其他语言编写的程序时,您的 CPU 将在缓存中保留一份“流行”RAM 块的副本。这是在硬件级别完成的。
Don't think of CPU cache as "other" or "more" memory...it's just a mechanism to keep some chunks of RAM close by.
不要将 CPU 缓存视为“其他”或“更多”内存……它只是一种将一些 RAM 块保持在附近的机制。
回答by Todd
I think you are mixing up two concepts. One, how does the C++ language store variables in memory. Two, how does the computer and operating system manage that memory.
我认为你混淆了两个概念。一、C++语言如何在内存中存储变量。二,计算机和操作系统如何管理该内存。
In C++, variables can be allocated on the stack, which is memory that is reserved for the program's use and is fixed in size at thread start or in dynamic memory which can be allocated on the fly using new. A compiler can also choose to store the variables on registers in the processor if analysis of the code will allow it. Those variables would never see the system memory.
在 C++ 中,变量可以在堆栈上分配,堆栈是为程序使用而保留的内存,在线程启动时大小固定,或者在动态内存中,可以使用 new 动态分配。如果代码分析允许,编译器还可以选择将变量存储在处理器的寄存器中。这些变量永远不会看到系统内存。
If a variable ends up in memory, the OS and the processor chip set take over. Both stack based addresses and dynamic addresses are virtual. That means that they may or may not be resident in system memory at any given time. The in memory variable may be stored in the systems memory, paged onto disk or may be resident in a cache on or near the processor. So, it's hard to know where that data is actually living. If a program hasn't been idle for a time or two programs are competing for memory resources, the value can be saved off to disk in the page file and restored when it is the programs turn to run. If the variable is local to some work being done, it could be modified in the processors cache several times before it is finally flushed back to the system memory. The code you wrote would never know this happened. All it knows is that it has an address to operate on and all of the other systems take care of the rest.
如果变量在内存中结束,操作系统和处理器芯片组接管。基于堆栈的地址和动态地址都是虚拟的。这意味着它们可能会或可能不会在任何给定时间驻留在系统内存中。in memory 变量可以存储在系统内存中,分页到磁盘上,或者可以驻留在处理器上或附近的缓存中。因此,很难知道这些数据实际上在哪里。如果一个程序有一段时间没有空闲或两个程序正在争夺内存资源,则可以将该值保存在页面文件中的磁盘中,并在程序运行时恢复。如果该变量是正在完成的某些工作的本地变量,则可以在处理器缓存中对其进行多次修改,然后最终将其刷新回系统内存。您编写的代码永远不会知道发生了这种情况。
回答by Adam Rosenfield
Variables can be held in a number of different places, sometimes in more than one place. Most variables are placed in RAM when a program is loaded; sometimes variables which are declared const
are instead placed in ROM. Whenever a variable is accessed, if it is not in the processor's cache, a cache miss will result, and the processor will stall while the variable is copied from RAM/ROM into the cache.
变量可以保存在许多不同的地方,有时在多个地方。加载程序时,大多数变量都放在 RAM 中;有时,声明的变量被const
放置在 ROM 中。每当访问变量时,如果它不在处理器的高速缓存中,就会导致高速缓存未命中,并且处理器将在变量从 RAM/ROM 复制到高速缓存时停顿。
If you have any halfway decent optimizing compiler, local variables will often instead be stored in a processor's register file. Variables will move back and forth between RAM, the cache, and the register file as they are read and written, but they will generally always have a copy in RAM/ROM, unless the compiler decides that's not necessary.
如果您有任何不错的优化编译器,则局部变量通常会存储在处理器的寄存器文件中。变量将在读取和写入时在 RAM、缓存和寄存器文件之间来回移动,但它们通常始终在 RAM/ROM 中具有副本,除非编译器决定不需要这样做。
回答by prashanth
The C++ language supports two kinds of memory allocation through the variables in C++ programs:
C++ 语言支持通过 C++ 程序中的变量进行两种内存分配:
Static allocation is what happens when you declare a static or global variable. Each static or global variable defines one block of space, of a fixed size. The space is allocated once, when your program is started (part of the exec operation), and is never freed. Automatic allocation happens when you declare an automatic variable, such as a function argument or a local variable. The space for an automatic variable is allocated when the compound statement containing the declaration is entered, and is freed when that compound statement is exited. The size of the automatic storage can be an expression that varies. In other CPP implementations, it must be a constant. A third important kind of memory allocation, dynamic allocation, is not supported by C++ variables but is available Library functions. Dynamic Memory Allocation
静态分配是当您声明静态或全局变量时发生的情况。每个静态或全局变量定义一个固定大小的空间块。该空间在您的程序启动时(exec 操作的一部分)分配一次,并且永远不会被释放。当您声明一个自动变量(例如函数参数或局部变量)时,就会发生自动分配。自动变量的空间在包含声明的复合语句进入时分配,并在复合语句退出时释放。自动存储的大小可以是变化的表达式。在其他 CPP 实现中,它必须是一个常量。C++ 变量不支持第三种重要的内存分配,动态分配,但可用的库函数。动态内存分配
Dynamic memory allocation is a technique in which programs determine as they are running where to store some information. You need dynamic allocation when the amount of memory you need, or how long you continue to need it, depends on factors that are not known before the program runs.
动态内存分配是一种技术,其中程序在运行时确定存储某些信息的位置。当您需要的内存量或您继续需要多长时间取决于程序运行之前未知的因素时,您需要动态分配。
For example, you may need a block to store a line read from an input file; since there is no limit to how long a line can be, you must allocate the memory dynamically and make it dynamically larger as you read more of the line.
例如,您可能需要一个块来存储从输入文件中读取的行;由于对一行的长度没有限制,因此您必须动态分配内存并在您阅读更多行时动态地使其变大。
Or, you may need a block for each record or each definition in the input data; since you can't know in advance how many there will be, you must allocate a new block for each record or definition as you read it.
或者,您可能需要为输入数据中的每个记录或每个定义一个块;由于您无法预先知道会有多少,您必须在阅读时为每个记录或定义分配一个新块。
When you use dynamic allocation, the allocation of a block of memory is an action that the program requests explicitly. You call a function or macro when you want to allocate space, and specify the size with an argument. If you want to free the space, you do so by calling another function or macro. You can do these things whenever you want, as often as you want.
使用动态分配时,内存块的分配是程序显式请求的操作。当您想分配空间时调用函数或宏,并用参数指定大小。如果你想释放空间,你可以通过调用另一个函数或宏来实现。你可以随时随地做这些事情。
Dynamic allocation is not supported by CPP variables; there is no storage class “dynamic”, and there can never be a CPP variable whose value is stored in dynamically allocated space. The only way to get dynamically allocated memory is via a system call , and the only way to refer to dynamically allocated space is through a pointer. Because it is less convenient, and because the actual process of dynamic allocation requires more computation time, programmers generally use dynamic allocation only when neither static nor automatic allocation will serve.
CPP 变量不支持动态分配;没有“动态”存储类,永远不可能有一个 CPP 变量的值存储在动态分配的空间中。获得动态分配内存的唯一方法是通过系统调用,而引用动态分配空间的唯一方法是通过指针。因为不太方便,而且动态分配的实际过程需要更多的计算时间,所以程序员一般只有在静态分配和自动分配都不会服务的情况下才使用动态分配。
For example, if you want to allocate dynamically some space to hold a struct foobar, you cannot declare a variable of type struct foobar whose contents are the dynamically allocated space. But you can declare a variable of pointer type struct foobar * and assign it the address of the space. Then you can use the operators ‘*' and ‘->' on this pointer variable to refer to the contents of the space:
例如,如果要动态分配一些空间来保存结构体 foobar,则不能声明内容为动态分配空间的结构体 foobar 类型的变量。但是您可以声明一个指针类型的变量 struct foobar * 并为其分配空间的地址。然后你可以在这个指针变量上使用运算符 '*' 和 '->' 来引用空间的内容:
{
struct foobar *ptr
= (struct foobar *) malloc (sizeof (struct foobar));
ptr->name = x;
ptr->next = current_foobar;
current_foobar = ptr;
}
回答by Joe Basirico
depending on how they are declared, they will either be stored in the "heap" or the "stack"
The heap is a dynamicdata structure that the application can use.
堆是应用程序可以使用的动态数据结构。
When the application uses data it has to be moved to the CPU's registers right before they are consumed, however this is very volatile and temporary storage.
当应用程序使用数据时,必须在它们被消耗之前将其移动到 CPU 的寄存器,但是这是非常易失的临时存储。