piripiri
piripiri

Reputation: 2015

Self-initialization of variable in its definition

The following C++ program compiles just fine (g++ 5.4 at least gives a warning when invoked with -Wall):

int main(int argc, char *argv[])
{
  int i = i; // !
  return 0;
}

Even something like

int& p = p;

is swallowed by the compiler.

Now my question is: Why is such an initialization legal? Is there any actual use-case or is it just a consequence of the general design of the language?

Upvotes: 11

Views: 2464

Answers (3)

Pete Becker
Pete Becker

Reputation: 76305

This is a side effect of the rule that a name is in scope immediately after it is declared. There's no need to complicate this simple rule just to prevent writing code that's obvious nonsense.

Upvotes: 2

M.M
M.M

Reputation: 141598

I guess the gist of your question is about why the second identifier is recognized as identifying the same object as the first, in int i = i; or int &p = p;

This is defined in [basic.scope.pdecl]/1 of the C++14 standard:

The point of declaration for a name is immediately after its complete declarator and before its initializer (if any), except as noted below. [Example:

unsigned char x = 12;
{ unsigned char x = x; }

Here the second x is initialized with its own (indeterminate) value. —end example ]

The semantics of these statements are covered by other threads:

Note - the quoted example differs in semantics from int i = i; because it is not UB to evaluate an uninitialized unsigned char, but is UB to evaluate an uninitialized int.

As noted on the linked thread, g++ and clang can give warnings when they detect this.


Regarding rationale for the scope rule: I don't know for sure, but the scope rule existed in C so perhaps it just made its way into C++ and now it would be confusing to change it.

If we did say that the declared variable is not in scope for its initializer, then int i = i; might make the second i find an i from an outer scope, which would also be confusing.

Upvotes: 1

Jesper Juhl
Jesper Juhl

Reputation: 31465

Just because the compiler accepts it (syntactically valid code) does not mean that it has well defined behaviour.

The compiler is not required to diagnose all cases of Undefined Behaviour or other classes of problems. The standard gives it pretty free hands to accept and translate broken code, on the assumption that if the results were to be undefined or nonsensical the programmer would not have written that code.

So; the absense of warnings or errors from your compiler does not in any way prove that your program has well defined behaviour. It is your responsibility to follow the rules of the language. The compiler usually tries to help you by pointing out obvious flaws, but in the end it's on you to make sure your program makes sense.

And something like int i = i; does not make sense but is syntactically correct, so the compiler may or may not warn you, but in any case is within its rights to just generate garbage (and not tell you about it) because you broke the rules and invoked Undefined Behaviour.

Upvotes: 1

Related Questions