c++variableslanguage-lawyer

Are variables formally a compile-time concept?


Note that this is a question. I know the common meaning of "variable", but I'm trying to understand what exactly the standard calls "variables". I'm writing some educational material and want to use the correct definitions.


Variables are commonly defined as "named objects", or more correctly "objects that have been declared" (since variables can be unnamed, but are always declared).

But there's a second point of view that variables are a compile-time concept. Under this definition, one declaration in the source code always corresponds to one variable, even if at runtime multiple objects are created from it.

Which one is correct?


Here's an example where this matters. Let's say you have

void foo(bool a)
{
    int x = 42;

    if (a)
        foo(false);
}

When you call foo(true), two instances of int x = 42; get to exist at the same time.

They are clearly two different objects, but are they technically different variables or the same variable?

If variables are a compile-time thing, then the two are the same variable.


The second definition sounds wrong at face value, but here we have a C++ committee member arguing that it's the correct one, for example.


Solution

  • With the disclaimer that my opinion is not entirely statistically independent from that cited, I agree strongly: the use of “variable” in the standard makes much more sense construed as “the abstract subject of declarations of certain forms” than as “a space of memory considered as having a certain type”. The standard frequently needs to talk about out the name of a variable, the scope within which it is declared, whether two declarations (perhaps in different translation units) declare the same variable, whether a variable is a reference or not, and so forth, and these things clearly pertain to the singular translation-time construct rather to anything that exists during execution. The strongest evidence for this last point is that all the rules about, say, a variable being usable in constant expressions apply even if it’s a non-static local variable in a function that is never called.

    On the other hand, the word “object” is used principally in ways that correspond to the “real data” concept: it has a value and an address and can be in or out of lifetime. This makes sense because the standard must support all runtime operations on objects created by new (placement or otherwise), which obviously are not variables.

    The standard is unfortunately not entirely consistent here, relying overmuch on the reader’s intuitive understanding of the intent when saying things like “A variable is introduced by the declaration […] of an object.” ([basic.pre]/7) and “block variables with automatic storage duration […] are initialized in declaration order” ([stmt.dcl]/2). Some progress has been made (C++17 stopped calling *this an “entity” as if it might be found by name lookup or something), and more is coming (the Reflection paper is doing further cleanup necessitated by wanting to describe what ^^x means).