22

Let's say I have some c++ code:

if (error)
    goto exit;
... 
// size_t i = 0; //error
size_t i;
i = 0;
...
exit:
    ...

I understand we should not use goto, but still why does

size_t i;
i = 0;

compile whereas size_t i = 0; doesn't?

Why is such behavior enforced by the standard (mentioned by @SingerOfTheFall)?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Akshit Khurana
  • 674
  • 6
  • 14

2 Answers2

18

You can't jump over initialization of an object.

size_t i = 0; 

is an initialization, while

size_t i;
i = 0;

is not.

The C++ Standard says:

It is possible to transfer into a block, but not in a way that bypasses declarations with initialization. A program that jumps from a point where a local variable with automatic storage duration is not in scope to a point where it is in scope is ill-formed unless the variable has POD type (3.9) and is declared without an initializer.

Alan Birtles
  • 32,622
  • 4
  • 31
  • 60
SingerOfTheFall
  • 29,228
  • 8
  • 68
  • 105
  • 4
    Could you please explain why is there a different behavior when they are functionally equivalent? I mean what is the rationale behind this standard. – Akshit Khurana Jul 03 '12 at 08:16
  • When you initialize a variable like this, it is still in scope even after the jump. That may cause big trouble if you will try to access it, and even more trouble in the end of the scope where it should be destroyed. If you have jumped over, the variable never existed, and trying to destroy it will result in a crash (probably segfault, I'm not sure). – SingerOfTheFall Jul 03 '12 at 08:24
  • 19
    The rationale is that in the `int i;` case, by defining the variable without an initializer, you are saying "I'm going to take responsibility to ensure that the variable is written before it gets read". The language lets you attempt that, and if the code following `exit` uses `i`, well, you failed. In the case of `int i = 0;`, the language enforces that any variable with an initializer is *always* initialized before use (as long as you don't use it in its own initializer, anyway). The only simple way the language can enforce that is to forbid your `goto`. – Steve Jessop Jul 03 '12 at 08:33
  • @SteveJessop This comment is much more useful and informative than answer itself! – ScienceDiscoverer Apr 03 '21 at 08:21
0

The reason for the rule is that jumping over an initialization leaves the object in an undefined state. When you get to the end of the function, destroying those uninitialized objects might not work.

One exception is obviously that

int   i;

leaves the int uninitialized anyway, so skipping that is just half bad.

If you want to leave a function early, a quick return is an option to avoid the goto.

Bo Persson
  • 90,663
  • 31
  • 146
  • 203