C++ Part I · Module 3 · Types, Variables, and Initialization
Objects, Variables and Types
Every program in the last two modules used int without a word about what an int is. That was deliberate — you needed a working build before the language was worth discussing. This module is the language, and it starts with the layer everything else stands on. Four words are about to be used very precisely: object, variable, value and type. In ordinary conversation they blur together, and for a week or two that costs nothing. It starts costing when you meet a reference, or a function parameter, or a copy, or an object whose lifetime has ended — because every one of those is a statement about one of these four things and not the others. This chapter separates them once, carefully, with the simplest picture that is still true. You will write very little code. You will finish able to say exactly what a declaration creates.
Foundation13 min readC++Part IFundamentalsObject Model
Part I · Module 3 · Chapter 3.1 · Objects, Variables and Types
1. One Line, Three Things
Here is a declaration you have written many times:
int cycle_count = 19;Ask what it created and most people say "a variable called cycle_count holding 19". That answer is useful and it is not precise enough, because it merges three separate things into one.
The three things are:
- A name —
cycle_count. Something you write in your source to refer to the thing. - An object — a region of storage, somewhere in memory, set aside to hold a whole number.
- A value —
19, the information currently held in that storage.
And one more thing governs all of it:
- A type —
int, which decides how much storage the object takes, how the bits in it are interpreted, and what you are allowed to do with it.
The rest of this chapter is those four ideas, one at a time.
2. The Box Picture, and Its Limits
The usual first picture is a box with a label on it and a number inside. It is a reasonable place to start, so start there:
- the label is the name,
- the box is the object,
- the number inside is the value.
That picture is correct as far as it goes, and it gets you through your first programs. Here is where it starts to mislead, so you know in advance:
- It suggests one box has exactly one label. In C++, more than one name can refer to the same object — that is what a reference is (Module 8).
- It suggests the box exists as long as the label does. It does not; an object has a lifetime, and it can end while a name that refers to it is still around. That is the source of an entire family of bugs.
- It suggests the number is in the box the way an apple is in a bowl. What is actually in the storage is a pattern of bits, and the type is what says that pattern means nineteen.
Keep the box as an intuition. The sections below replace each weak part of it with something that stays true.
3. An Object Is Storage With a Type
In C++, object means something specific, and it is not what the word means in Java or Python:
An object is a region of storage with a type and a lifetime.
Chapter 1.1 §5 made the first half of this point and it is worth repeating because it catches almost everyone: an int is an object. A double is an object. An array is an object. "Object" does not mean "instance of a class" in C++ — class instances are objects, but so is every int you have ever declared.
Three parts, each doing real work:
Storage. The object occupies actual memory. It has a size, and it sits somewhere. You will not usually care where until Module 8 gives you a way to ask.
A type. The storage is not raw bytes you can interpret however you like. The type says how many bytes there are and what the bits in them mean. This is the part the box picture leaves out, and §5 is about it.
A lifetime. The object comes into existence at some point and stops existing at another. Using it outside that window is invalid — not "returns a strange number", but genuinely undefined. The rules are Module 7's and Module 10's; what matters here is knowing the property exists, because "the object is gone but the name is still in scope" is a real situation and the box picture hides it.
4. A Variable Is a Name
A variable is a name introduced by a declaration, which denotes an object.
That sounds like splitting hairs. Here is why it is not.
int cycle_count = 19;cycle_count is a name that exists in your source code. It does not exist in the running program — the machine does not look up names at run time. When the compiler meets cycle_count in a later line, it works out which object you meant and emits code that works on that storage directly.
So:
| Thing | Where it exists |
|---|---|
The name cycle_count | In your source, and in the compiler's bookkeeping |
| The object | In memory, while the program runs |
| The value | In that object, at a given moment |
This distinction is what makes the next three modules readable. When Module 6 says a function parameter is a copy, it means a second object was created. When Module 8 says a reference is another name for the same object, it means exactly that — a second name, no second object. Neither sentence can be stated, let alone understood, if name and object are the same idea in your head.
5. The Type Is What Makes the Bits Mean Something
This is the idea the whole module rests on.
Storage holds bits. Bits on their own mean nothing — the same pattern can be a whole number, a fraction, or a character, depending on how you read it. The type is the instruction for reading it.
A type decides three things:
- How much storage the object takes. Chapter 3.2 measures this.
- How the bits are interpreted. The same 32 bits are one number read as a signed integer and a different one read as unsigned (Chapter 3.3), and something else again read as a floating-point value (Chapter 3.5).
- Which operations make sense. You can divide two numbers. Dividing two booleans is not a meaningful request, and the type system is what lets the compiler say so.
Point 3 is worth dwelling on, because it is the one beginners undervalue. The type is not only a storage decision — it is how you tell the compiler what kind of thing you are working with, so that it can reject the operations that do not belong.
Chapter 1.1 §6 measured abstraction costing nothing at run time. This is the same idea from the other end: a type is a compile-time concept. It governs what the compiler accepts and what machine code it emits. By the time the program runs, there is no type stored anywhere alongside the value — only bits that were already interpreted correctly when the code was generated.
6. Watching the Value Change
A short program that makes the distinction visible:
#include <iostream>
int main()
{
int cycle_count = 19;
std::cout << "cycle_count = " << cycle_count << '\n';
cycle_count = 23;
std::cout << "cycle_count = " << cycle_count << '\n';
return 0;
}Expected output:
cycle_count = 19
cycle_count = 23Now say precisely what happened on the assignment line, because the loose description hides the point.
The loose version: "cycle_count changed from 19 to 23."
The precise version: the name still denotes the same object; the object still occupies the same storage; the object's type is still int; only the value held in it changed.
Three of the four things were unaffected. That is the normal case, and it is why "the variable changed" is a serviceable shorthand — but you now know which of the four things a shorthand like that is actually talking about.
7. Where the Distinction Starts Paying
Not an abstract exercise. Each of these is a real situation where merging the four ideas produces a wrong answer.
Two names, one object. A function that takes a reference operates on the caller's object; a function that takes a value operates on a copy. Same syntax at the call site, completely different consequences. Modules 6 and 8.
The object outlives the value, or the name outlives the object. A name can still be in scope after the object it referred to has ceased to exist. The box picture says the box is still there; the language says reading it is invalid. Modules 7 and 10.
Copying. When you copy something, you create a second object and give it a value based on the first. Whether that is cheap or expensive, and whether the two objects then share anything, is the entire subject of Module 13.
Type-driven interpretation. The same bits read through two different types give two different values. That is Chapter 3.3 for integers and 3.5 for floating point, and it is the reason a wrongly-typed register read gives a plausible wrong answer rather than an error.
In engineering terms the last one matters most. A 32-bit register value read into the wrong type does not fail loudly — it produces a number that looks reasonable and is not. Chapter 1.2 §3 showed exactly this with an address sorting into the wrong place.
8. Mistakes Worth Making Once
Saying "variable" when you mean the object. Harmless until you meet references, at which point "the variable was modified" becomes ambiguous — which name, which object? Say "the object" when you mean the storage.
Thinking "object" means "class instance". In C++ it means typed storage. An int is an object. This trips up everyone arriving from Java or Python, and it makes half the standard's wording unreadable until it is fixed.
Thinking the type is stored with the value at run time. It is not. The type is a compile-time property that decides what code gets generated. There is no tag in memory saying "this is an int" that the program can consult.
Thinking a name guarantees a live object. The name being visible and the object being alive are different conditions. They coincide most of the time, and the exceptions are where the hard bugs live.
Believing the value is what the bits "are". The bits are a pattern. The value is what that pattern means under this type. Change the type and you change the value without touching a single bit.
9. What You Should Be Able to Say Now
- One declaration creates a name, an object and a value, governed by a type. They are four different things.
- An object is a region of storage with a type and a lifetime. In C++ this includes every
int— it does not mean "class instance". - A variable is a name introduced by a declaration, which denotes an object. Names exist in your source; objects exist in memory while the program runs.
- A value is the information an object currently represents.
- A type decides how much storage is used, how the bits are interpreted, and which operations are allowed.
- A type is a compile-time concept. Nothing in memory records it at run time.
- Not every object has a name, and more than one name can denote one object.
- On assignment, only the value changes — the name, the object and the type stay the same.
- The same bits under two different types are two different values, which is why a wrongly-typed hardware read gives a plausible wrong answer rather than an error.
- The box picture is a starting intuition, not the model. It cannot express two names for one object, or an object whose lifetime has ended.
10. Exercises
Exercise 1 — name the four. For double supply_voltage = 1.8; identify the name, the object, the value and the type, in one short phrase each.
Exercise 2 — say it precisely. Rewrite this sentence so it distinguishes the four ideas: "The variable changed from 19 to 23."
Exercise 3 — which is wrong? A colleague says: "At run time the program checks that cycle_count is an int before doing the addition." Explain what is wrong with that, and when the check actually happens.
Exercise 4 — the unnamed object. In int total = 19 + 4;, how many values appear, and how many of them are held in objects that have a name? Explain your count.
Exercise 5 — the engineering case. A 32-bit register value is read into an object of the wrong type. Explain, using §5, why this produces a believable wrong number rather than an error, and name which of the four ideas was misapplied.
Exercise 6 — stress the box. Give one specific thing that is true in C++ and that the box-with-a-value picture cannot express. Say which later module teaches it.
Exercise 7 — object or not? For each, say whether it is an object in the C++ sense: (a) int error_count; (b) the number 42 written in your source; (c) the name error_count; (d) the type int.
11. Summary
- One declaration, four ideas: a name, an object, a value and a type.
- An object is storage with a type and a lifetime — and in C++ that includes every
int, not only class instances. - A variable is a name that denotes an object. Names live in the source; objects live in memory.
- A value is what the object currently represents; assignment changes only that.
- A type decides size, interpretation and permitted operations, and it is a compile-time concept with nothing recorded in memory at run time.
- Names and objects are not paired one to one — some objects have no name, and one object can have several.
- The same bits under a different type are a different value, which is why a mis-typed hardware read is believable and wrong.
- The box picture is a first intuition, useful and incomplete. Keep it; do not trust it past this chapter.
The type was described here as the thing that decides how much storage an object takes — without saying how much that is for any particular type. That question has a more interesting answer than you might expect, because the C++ standard deliberately does not fix most of it. Chapter 3.2 takes the fundamental types one at a time, measures them on a real machine, and separates three things that get confused constantly: what the language guarantees, what your platform happens to do, and what a number printed by sizeof is actually telling you.
Standards & specifications
- Governing standard
- ISO/IEC 14882 (the C++ language standard)(opens ISO/IEC (JTC 1/SC 22/WG 21) in a new tab)
Defines the C++ language and its standard library — the type system and templates, the object model and object lifetime, initialisation and overload resolution, the memory model and the containers, algorithms and utilities the library provides. Like C's standard it is a FAMILY of editions (C++98/03, C++11, C++14, C++17, C++20, C++23) and the editions are NOT interchangeable: a feature this curriculum relies on may be unavailable, differently specified or merely proposed in another edition, so each lesson names the edition its claim depends on. It does not define any foreign-function interface to a hardware description language, nor what a compiler actually emits, nor platform behaviour on real silicon — those are the implementation's and the device's contracts. Working drafts published by WG21 are freely available and are what most engineers read day to day; a draft is not the published standard.
This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.
Where this fits
Part of the C++ Programming curriculum.
