Variables are Aliases, not Objects!

This article mainly concerns C++, but can be applied to any programming language with variables. There is an important distinction to make between variables and objects when learning to program: variables are not objects. A variable is an alias for an object. An object may have multiple aliases, or none.

A great example of this concept is C++ references - in this code snippet, there is one object with two aliases:

int a = 0;
int &b = a;

The int object happens to be stored on the stack (has local scope), contains the value 0, and has aliases a and b. You don't say that a and b refer to the object (that is what pointers do); instead you say that a and b are the object (even though a and b are aliases to the object). A reference is another name for the same object.

In C and C++, there are also pointers. In Java, they are called references, but they are the same thing as C++ pointers (not C++ references). Pointers are themselves objects, and they are made up of whatever data is needed for them to dynamically refer to other objects or no object. In this code snippet, there are two objects:

int a = 0;
int *p = &a;

The first object, stored on the stack, is aliased by a and referred to by the second object, which is also on the stack. The second object is aliased by p, and refers to the object aliased by a. In other words, a is an object and p is an object that refers to a. This is in stark contrast to the previous code snippet with the C++ reference - many people attempting to learn C++ struggle to understand the conceptual difference between a pointer and a reference. A pointer is an object which holds the address of another object.

In some cases, a compiler may implement a reference as a pointer. This underlying implementation detail, however, should be ignored - it is the wrong way of thinking about references and pointers. The primary difference between a C++ pointer and a C++ reference is that a C++ pointer is an object which may dynamically refer to other objects and a C++ reference is an alias to only one object. You can't "change" what a reference aliases; you can change what a pointer refers to, including making it refer to nothing.

Unfortunately, Java makes a completely different kind of distinction - variables are either primitive (int, boolean, reference), or a Class type (String, Scanner, OutputStream). Java references are similar to C++ pointers, but they may not refer to primitive objects - Java references may only refer to Class objects. I don't know why this distinction is made, but because of it, it is not possible to port C++'s std::swap to Java.

What are Objects?

Objects exist in memory, and they are just a bunch of bits that are either on or off. Variables are in your written code and are aliases to objects - they give the memory meaning; a consistent way to interpret the object - variables don't actually exist at all in memory. Recall that in C++, you cannot have a pointer to a reference - and this makes sense, since a reference is just another alias to an object and is not itself an object. Pointers may only refer to objects, not variables/aliases. (PHP has variable variables, but they're generally considered a bad idea.)

The distinction between a variable (a construct of the human mind) and an object (a bunch of memory) is one of the most important distinctions to make in C++. A bunch of memory has no underlying data type. The distinction we make between ints and floats is non-existent in memory (aside from debugging information). Meaning is in the eye of the beholder - data types are determined by how we treat that data. Variables/aliases let us tell the compiler how memory should be treated, so that the compiler can tell us when we mistreat it. Once the code is converted to machine code, that information is gone. (Java compiles to bytecode files and only converts to machine code at runtime.)

Owning and Non-Owning Aliases

So far, I haven't gone over the relationship between the scope of variables and the lifetime of objects. The easiest way to explain and think about it is to differentiate between owning aliases and non-owning aliases. A non-owning alias is a C++ reference - it does not affect the lifetime of the object it aliases (except for special cases involving temporaries). An object can have any number of non-owning aliases, from 0 to infinity. Owning aliases, on the other hand, "own" their object. (Hm, I wonder why they are called "owning aliases" to begin with?)

The lifetime of objects that have an owning alias is directly related to the scope of that owning alias. An object may have 1 or 0 owning aliases, and this will not change during its lifetime - I don't even think you could do any hackery or evil magic to change that. An example of an object with an owning alias is a variable on the stack. An example of an object with no owning alias is an object created with the new operator.

The lifetime of objects with no owning alias is arbitrary - it depends on when delete is called (more specifically, when the destructor is called), if ever. In any case, an object's lifetime starts after the constructor returns and ends upon calling the destructor. This definition accounts for placement new and manually calling the destructor, however seldom-used that may be. It also happens to be he definition used by the C++ Standard, more or less.

What have we learned?

Remember these key points, and you will have no problem understanding your code.