简体   繁体   中英

Where are variables in C++ stored?

Where are variables in C++ stored?

Inside the RAM or the processor's cache?

Named variables are stored:

  • On the stack, if they're function-local variables.
    C++ calls this "automatic storage" 1 and doesn't require it to actually be the asm call stack, and in some rare implementations it isn't. But in mainstream implementations it is.
  • In a per-process data area if they are global or static .
    C++ calls this "static storage class"; it's implemented in asm by putting / reserving bytes in section .data , .bss , .rodata , or similar.

If the variable is a pointer initialized with int *p = new int[10]; or similar, the pointer variable p will go in automatic storage or static storage as above. The pointed-to object in memory is:

  • On the heap (what C++ calls dynamic storage), allocated with new or malloc , etc.
    In asm, this means calling an allocator function, which may ultimately get new memory from the OS via some kind of system call if its free-list is empty. "The heap" isn't a single contiguous region in modern OSes / C++ implementations.

C and C++ don't do automatic garbage collection, and named variables can't themselves be in dynamic storage ("the heap"). Objects in dynamic storage are anonymous, other than being pointed-to by other objects, some of which may be proper variables. (An object of struct or class type, as opposed to primitive types like int , can let you refer to named class members in this anonymous object. In a member function they even look identical.)

This is why you can't (safely/usefully) return a pointer or reference to a local variable.


This is all in RAM, of course . Caching is transparent to userspace processes, though it may visibly affect performance.

Compilers may optimize code to store variables in registers. This is highly compiler and code-dependent, but good compilers will do so aggressively.


Footnote 1: Fun fact: auto in C++03 and earlier, and still in C, meant automatic storage-class , but now (C++11) it infers types.

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.

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 any memory access goes through the cache.

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. :-)

Variables are usually stored in RAM. This is either on the Heap (eg global variables, static variables in methods/functions) or on the Stack (eg non-static variables declared within a method/function). Stack and Heap are both RAM, just different locations.

Pointers are a bit special. Pointers themselves follow the rules above but the data they point to is typically stored on the Heap (memory blocks created with malloc , objects created with new ). Yet you can create pointers pointing to stack memory: int a = 10; int * b = &a; int a = 10; int * b = &a; ; b points to the memory of a and a is stored on the stack.

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 as well.

The compiler can only decide which 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 certain systems can actually only be performed if the data is in a register, in that case the compiler must move data to a register before performing the operation and can only decide when to move the data back to RAM.

Compilers will always try to keep the most often accessed data in a register. When a method/function is called, usually all register values are written back to RAM, unless the compiler can say for sure that the called function/method will not access the memory where the data came from. Also on return of a method/function it must write all register data back to RAM, otherwise the new values would be lost. The return value itself is passed in a register on some CPU architectures, it is passed via stack otherwise.

Variables in C++ are stored either on the stack or the heap.

stack:

int x;

heap:

int *p = new int;

That being said, both are structures built in RAM.

If your RAM usage is high though windows can swap this out to disk.

When computation is done on variables, the memory will be copied to registers.

C++ is not aware of your processor's cache.

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.

Don't think of CPU cache as "other" or "more" memory...it's just a mechanism to keep some chunks of RAM close by.

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.

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.

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.

The C++ language supports two kinds of memory allocation through the variables in C++ programs:

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

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.

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:

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

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.

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.

depending on how they are declared, they will either be stored in the " heap " or the " stack "

The heap is a dynamic data 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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