The Differences Between Initialize, Define, Declare a Variable

What distinguishes the declaration, the definition and the initialization of a variable?

Declaration

Declaration, generally, refers to the introduction of a new name in the program. For example, you can declare a new function by describing it's "signature":

void xyz();

or declare an incomplete type:

class klass;
struct ztruct;

and last but not least, to declare an object:

int x;

It is described, in the C++ standard, at §3.1/1 as:

A declaration (Clause 7) may introduce one or more names into a translation unit or redeclare names introduced by previous declarations.

Definition

A definition is a definition of a previously declared name (or it can be both definition and declaration). For example:

int x;
void xyz() {...}
class klass {...};
struct ztruct {...};
enum { x, y, z };

Specifically the C++ standard defines it, at §3.1/1, as:

A declaration is a definition unless it declares a function without specifying the function’s body (8.4), it contains the extern specifier (7.1.1) or a linkage-specification25 (7.5) and neither an initializer nor a function- body, it declares a static data member in a class definition (9.2, 9.4), it is a class name declaration (9.1), it is an opaque-enum-declaration (7.2), it is a template-parameter (14.1), it is a parameter-declaration (8.3.5) in a function declarator that is not the declarator of a function-definition, or it is a typedef declaration (7.1.3), an alias-declaration (7.1.3), a using-declaration (7.3.3), a static_assert-declaration (Clause 7), an attribute- declaration (Clause 7), an empty-declaration (Clause 7), or a using-directive (7.3.4).

Initialization

Initialization refers to the "assignment" of a value, at construction time. For a generic object of type T, it's often in the form:

T x = i;

but in C++ it can be:

T x(i);

or even:

T x {i};

with C++11.

Conclusion

So does it mean definition equals declaration plus initialization?

It depends. On what you are talking about. If you are talking about an object, for example:

int x;

This is a definition without initialization. The following, instead, is a definition with initialization:

int x = 0;

In certain context, it doesn't make sense to talk about "initialization", "definition" and "declaration". If you are talking about a function, for example, initialization does not mean much.

So, the answer is no: definition does not automatically mean declaration plus initialization.

Declaring vs Initializing a variable?

Edit: @ThisClark said something in the comments, and I went to prove him wrong, and upon reading the spec some more I learned something:

Here's an informative except from the specification:

A var statement declares variables that are scoped to the running execution context’s VariableEnvironment. Var variables are created when their containing Lexical Environment is instantiated and are initialized to undefined when created. [...] A variable defined by a VariableDeclaration with an Initializer is assigned the value of its Initializer’s AssignmentExpression when the VariableDeclaration is executed, not when the variable is created.

Based on my reading of this, the following points describe the behavior (and "correct-ish" usage of the terms) you asked about in your question:

  • A variable declaration (e.g., var foo) causes that variable to be created as soon as the "lexical environment" is instantiated. For example, if that variable were defined within a function body, that function is the "lexical environment", and so variable creation coincides with the instantiation of the function itself.

  • Obviously, variable declarations may or may not be created with an initializer (i.e., the right-hand expression that resolves to the variable's initial value). That's a pretty non-specification usage of the term "initial value", though... let's dig into that a bit more:

  • Technically, per the specification notes here, all variables are initialzed with the value undefined:

    variables are created [...] and are initialized to undefined

    Emphasis on "technically" there, as this is largely academic if an initializer was also provided.

  • Based on what we've already covered, it should be understood that the statement var foo; could exist anywhere within a function body, and moving it anywhere else within the same function would have no effect on the runtime semantics of the function itself (regardless of if/where any actual assignments or other references to foo take place). If that's still confusing, re-read the previous points.

  • The last bit of behavior is the most intuitive part, and that's the assignment of the initializer. This assignment takes place when that line of code is actually executed (which, again, isn't the same point in time when the variable technically got created).

So, to quickly recap:

  • All variable declarations (that use var) are always initialized with undefined upon the initialization of their lexical environment.
  • This initialization probably doesn't count as an assignment, in the technical sense (ha, @ThisClark, you were wrong!!). :)
  • Assignments are the easy part, as they behave the way (and at the point in time) that you expect.

Hope that helps (and that I didn't terribly misinterpret the spec!).

Java: define terms initialization, declaration and assignment

assignment: throwing away the old value of a variable and replacing it with a new one

initialization: it's a special kind of assignment: the first. Before initialization objects have null value and primitive types have default values such as 0 or false. Can be done in conjunction with declaration.

declaration: a declaration states the type of a variable, along with its name. A variable can be declared only once. It is used by the compiler to help programmers avoid mistakes such as assigning string values to integer variables. Before reading or assigning a variable, that variable must have been declared.

How does declaration, definition and initialization work? I've stated how I understand it and would like to get corrected

Yes, in simple terms you are correct. The standard draft devotes a page or so to declarations and definitions in par. 6.1. I liked how it described declarations (emphasis by me):

A declaration (Clause 10) may introduce one or more names into a translation unit or redeclare names
introduced by previous declarations.

The standard is vague about the nature of these names (in particular it doesn't mention "objects", "variables" or "types"!) because there is a great variety: Classes, functions, enum declarators, plain old variables, parameters, static class members etc.

The standard is also vague about the nature of this "introduction" because it varies as well. The common denominator is that a declaration gives the compiler enough information about the name to work with it it, although perhaps only in a restricted manner. For example, after the forward declaration of a class (class MyClass;) the compiler knows only that the name designates a type; but that's enough to define pointers to it (because all pointers to objects are created equal). It is not enough though to create an object of that type or call a method: The data and function members are, after all, unknown.

One can probably say that a declaration often specifies the outward properties — enough to use a name in some manner —, while a definition specifies the inner workings, i.e. what happens when it is being used.

For example, probably the most common "pure" declarations are function declarations, typically in headers. They inform the compiler how they can be called and which code must be produced to call them. A function definition, by contrast, specifies what happens when the function is called.

Similarly for a variable declaration vs. definition: *How can it be used vs. what happens when it is being used (which memory is manipulated).

The standard then goes on for half a page to list declarations which are not also definitions; about 10% of that are unknown terms for me (not sure whether that reflects badly on the standard or on me). With variables though, a declaration is, as you said, typically a definition unless it comes with the extern specifier and no initialization.

What is the difference between a definition and a declaration?

A declaration introduces an identifier and describes its type, be it a type, object, or function. A declaration is what the compiler needs to accept references to that identifier. These are declarations:

extern int bar;
extern int g(int, int);
double f(int, double); // extern can be omitted for function declarations
class foo; // no extern allowed for type declarations

A definition actually instantiates/implements this identifier. It's what the linker needs in order to link references to those entities. These are definitions corresponding to the above declarations:

int bar;
int g(int lhs, int rhs) {return lhs*rhs;}
double f(int i, double d) {return i+d;}
class foo {};

A definition can be used in the place of a declaration.

An identifier can be declared as often as you want. Thus, the following is legal in C and C++:

double f(int, double);
double f(int, double);
extern double f(int, double); // the same as the two above
extern double f(int, double);

However, it must be defined exactly once. If you forget to define something that's been declared and referenced somewhere, then the linker doesn't know what to link references to and complains about a missing symbols. If you define something more than once, then the linker doesn't know which of the definitions to link references to and complains about duplicated symbols.


Since the debate what is a class declaration vs. a class definition in C++ keeps coming up (in answers and comments to other questions) , I'll paste a quote from the C++ standard here.

At 3.1/2, C++03 says:

A declaration is a definition unless it [...] is a class name declaration [...].

3.1/3 then gives a few examples. Amongst them:


[Example: [...]
struct S { int a; int b; }; // defines S, S::a, and S::b [...]
struct S; // declares S
—end example

To sum it up: The C++ standard considers struct x; to be a declaration and struct x {}; a definition. (In other words, "forward declaration" a misnomer, since there are no other forms of class declarations in C++.)

Thanks to litb (Johannes Schaub) who dug out the actual chapter and verse in one of his answers.

What is the difference between declaration and definition in Java?

The conceptual difference is simple:

  • Declaration: You are declaring that something exists, such as a class, function or variable. You don't say anything about what that class or function looks like, you just say that it exists.

  • Definition: You define how something is implemented, such as a class, function or variable, i.e. you say what it actually is.

In Java, there is little difference between the two, and formally speaking, a declaration includes not only the identifier, but also it's definition. Here is how I personally interpret the terms in detail:

  • Classes: Java doesn't really separate declarations and definitions as C++ does (in header and cpp files). You define them at the point where you declare them.

  • Functions: When you're writing an interface (or an abstract class), you could say that you're declaring a function, without defining it. Ordinary functions however, are always defined right where they are declared. See the body of the function as its definition if you like.

  • Variables: A variable declaration could look like this:

      int x;

(you're declaring that a variable x exists and has type int) either if it's a local variable or member field. In Java, there's no information left about x to define, except possible what values it shall hold, which is determined by the assignments to it.

Here's a rough summary of how I use the terms:

abstract class SomeClass {                // class decl.
// \
int x; // variable decl. |
// |
public abstract void someMethod(); // function decl. |
// |
public int someOtherMethod() { // function decl. |
// | class
if (Math.random() > .5) // \ | def.
return x; // | function definition |
else // | |
return -x; // / |
// |
} // |
} // /

Meanings of declaring, instantiating, initializing and assigning an object

Declaring - Declaring a variable means to introduce a new variable to the program. You define its type and its name.

int a; //a is declared

Instantiate - Instantiating a class means to create a new instance of the class. Source.

MyObject x = new MyObject(); //we are making a new instance of the class MyObject

Initialize - To initialize a variable means to assign it an initial value.

int a; //a is declared
int a = 0; //a is declared AND initialized to 0
MyObject x = new MyObject(); //x is declared and initialized with an instance of MyObject

Assigning - Assigning to a variable means to provide the variable with a value.

int a = 0; //we are assigning to a; yes, initializing a variable means you assign it a value, so they do overlap!
a = 1; //we are assigning to a

Is there a difference between initializing a variable and assigning it a value immediately after declaration?

The behavior must be identical, but any differences in the generated code really depend on the compiler.

For example, the compiler could generate this for the initialized variable:

somefunction:
pushl %ebp
movl %esp, %ebp
pushl $2 ; allocate space for x and store 2 in it
...

and this for the uninitialized, but later assigned variable:

somefunction:
pushl %ebp
movl %esp, %ebp
subl $4, %esp ; allocate space for x
...
movl $2, -4(%ebp) ; assign 2 to x
...

The C standard does not mandate the generated code to be identical or non-identical in these cases. It only mandates identical behavior of the program in these two cases. And that identical behavior does not necessarily imply identical machine code.

Is there any difference between declared and defined variable

A let or const variable can only be declared once - that is, when you have let <variableName> in a scope, you have declared <variableName> in that scope, and cannot declare it again in that scope.

From the previously linked question:

When there's assignment, the right-hand side is parsed first; if the right-hand side throws an error, it never gets to the left-hand side, and the variable declared with let never gets properly initialized; it'll stay in the demilitarized zone / temporal dead zone forever

You can't re-declare a variable that's already been declared, even though the attempted assignment during initialization threw an error.

But on line 4, x=3 should do a proper assignment and it should remove x from TDZ. But that also fails. I fail to understand that

After a variable has been initialized (for example, the let x runs), it can be assigned to. But just like you can't assign to a variable before its let initialization, you also can't assign to a variable later, when its initialization did not complete successfully: