Dataslope logoDataslope

Variables and Memory

What variables really are — names for boxes in memory — and how the compiler tracks them.

In every language, a variable is just a name you give to a place in memory. In C++ that statement is almost literally true. When you write

int x = 42;

you are telling the compiler:

  1. Reserve enough memory for an int (typically 4 bytes).
  2. Remember that the name x refers to that piece of memory.
  3. Initialize it to the value 42.

You can later read the variable (std::cout << x;) or write to it (x = 99;). The name x stays bound to the same place in memory for as long as the variable is alive.

Declarations vs definitions vs assignments

These three words sound similar but mean different things.

CodeWhat it does
int x;Definition. Reserves memory; the value is uninitialized (garbage).
int x = 42;Definition + initialization. Reserves memory and gives it the value 42.
extern int x;Declaration only. "Promise: an int named x is defined somewhere else."
x = 99;Assignment. x must already exist; overwrite its value.

Beginners almost never write the third form, but they care a lot about the difference between the second and the fourth: creating a variable vs changing one.

Always initialize

C++ does not zero-initialize local variables by default. If you forget to give a local variable a value, reading it is undefined behavior — the compiler is allowed to do anything in response, including making your program appear to work in testing and fail in production. Make this a habit:

Code Block
C++ 20 (202002L)

Modern C++ tip: write int x{}; (called value initialization) when you want a default zero. The empty braces are the safest way to ask for a sensible starting value.

Types are promises about memory

Every variable in C++ has a type. The type is not just a label; it tells the compiler:

  • How much memory to reserve. An int is 4 bytes (typically), a double is 8 bytes, a char is 1 byte.
  • How to interpret those bytes. The same 4 bytes might encode an integer, a float, or four ASCII characters; the type tells the compiler which interpretation to use.
  • What operations are allowed. You can add two ints. You can index into an int*. You cannot multiply two std::strings.

This is why C++ is called a statically typed language: every variable's type is decided at compile time and the compiler enforces it. You cannot do x = "hello"; if x is an int. The compiler catches the bug before your program ever runs.

A tour of fundamental types

You will use these constantly:

TypeWhat it storesTypical sizeRange / notes
booltrue / false1 byteyes/no
charone character or small integer1 byte-128..127 or 0..255
intinteger4 bytesabout ±2.1 billion
longlarger integer4 or 8 bytesplatform-dependent
long longeven larger8 bytesabout ±9.2 quintillion
unsigned intnon-negative integer4 bytes0..4.29 billion
floatsingle-precision floating-point4 bytes~7 decimal digits
doubledouble-precision floating-point8 bytes~15 decimal digits
std::stringgrowable string of charactersdependsfrom <string>

When you don't know which integer type to use, reach for int. When you need to be precise about width (say, a 16-bit network protocol field), use <cstdint> types like int16_t, int32_t, int64_t.

Code Block
C++ 20 (202002L)

auto: let the compiler infer the type

Modern C++ lets you write auto instead of spelling the type out, and the compiler will fill in the right type by looking at the initializer. This is handy for long type names.

Code Block
C++ 20 (202002L)

auto does not mean "no type." It means "you, the compiler, figure out the type and lock it in." x is just as much an int as if you had written int x;.

Scope: where a variable is visible

A variable's scope is the region of source code where its name makes sense. The most common rule: a variable's scope starts at its declaration and ends at the closing } of the smallest enclosing block.

Code Block
C++ 20 (202002L)

Smaller scopes are better. Declare each variable as close to its first use as possible, and the program becomes much easier to read and reason about.

Lifetime: when a variable lives and dies

Closely related to scope is lifetime: the period of time during execution when the variable's memory is valid.

For a local variable, the lifetime equals the scope: the variable is born when execution reaches its declaration and dies at the closing } of its block. For a global variable (declared outside any function) the lifetime is the entire program. For a heap-allocated object (with new) the lifetime is whatever you say; we will spend whole chapters on that.

A common bug is returning a pointer or reference to a local variable: by the time the caller uses it, the variable has been destroyed.

int* bad() {
    int x = 42;
    return &x;     // returning the address of a local --
}                  // -- x dies HERE, the pointer dangles.

This is undefined behavior. We will cover pointers, references, and how to avoid this trap properly in upcoming chapters.

const: variables that don't vary

If a "variable" is never supposed to change, mark it const. The compiler will enforce that, and you'll never have an accidental overwrite.

Code Block
C++ 20 (202002L)

A useful habit: declare everything const by default, and only remove const from things that genuinely need to change. Most of your variables will turn out to be effectively constant once you inspect them.

Implicit conversions and a famous footgun

C++ will sometimes silently convert one type to another. Most are harmless (int to double); some are dangerous (double to int truncates, signed to unsigned wraps).

Code Block
C++ 20 (202002L)

Modern advice: prefer static_cast<T>(value) when you genuinely want a conversion. It makes the intent explicit and easier to grep for.

Challenge: variable practice

Challenge
C++ 20 (202002L)
Celsius to Fahrenheit

Implement celsius_to_fahrenheit so the program prints 98.6 (no trailing newline, just 98.6).

The formula is F = C * 9/5 + 32. Watch out: 9/5 in integer arithmetic is 1, not 1.8!

Test your understanding

QuestionSelect one

In C++, what is a variable, in the simplest physical sense?

A label attached to a function.

A copy of data stored in the CPU's registers permanently.

A name bound to a region of memory of a known type and size.

A pointer to a row in a database table.

QuestionSelect one

What happens if you read a local variable that you never initialized?

It is always zero.

The compiler refuses to compile the program.

You get undefined behavior: the bytes in that memory are whatever happened to be there, and any code that uses them may misbehave.

The runtime throws a NullVariableException.

QuestionSelect one

What does const do to a variable?

It makes the variable live in the heap.

It guarantees the variable will be optimized away.

It tells the compiler that this variable's value must not change after initialization, and prevents any code that tries to.

It exports the variable to other source files.

QuestionSelect one

Why is auto not a violation of static typing?

Because auto makes the variable dynamically typed.

Because the compiler still determines a single concrete type at compile time and locks it in; auto only saves you from spelling the type out.

Because auto only works in templates.

Because the type is decided at runtime based on what you assign first.

Next: a closer look at types themselves — what kinds C++ has, and how to choose between them.

On this page