78

I get a "transfer of control bypasses initialization of:" error when i try to build the following switch:

switch (retrycancel)
{
    case 4:    //The user pressed RETRY
        //Enumerate all visible windows and store handle and caption in "windows"
        std::vector<MainHandles::window_data> windows = MainHandles().enum_windows().get_results(); 
        break;

    case 2: 
        //code
}

It has something to do with my calling my enumerate function. If it is not allowed to call a function from within a switch, is there a workaround for this kind of problem?

Lumpi
  • 2,697
  • 5
  • 38
  • 47

2 Answers2

121

section 6.6.4 of the C++ standard:

The goto statement unconditionally transfers control to the statement labeled by the identifier. The identifier shall be a label (6.1) located in the current function.

section 6.7 of the C++ standard:

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

Emphasis added by me. Since switch is really goto in disguise, you're encountering this behavior. To solve this, add braces if you must use a switch

switch (retrycancel)
    {
    case 4:
    {
        const std::vector<MainHandles::window_data> windows(
            MainHandles().enum_windows().get_results()
        );
        break;
    }
    case 2: 
        //code
    }

or refactor into if/else

if (retrycancel == 4) {
    const std::vector<MainHandles::window_data> windows(
        MainHandles().enum_windows().get_results()
    );
} else if (retrycancel == 2)
    // code
} else {
    ...
}

Though it's not obvious to me what you're hoping to accomplish with creating the windows vector inside a switch, so you may want to rethink your design. Note I added a const qualifier to windows since it's not modified in your example.

Sam Miller
  • 23,808
  • 4
  • 67
  • 87
  • 1
    Thank you to for your answer, It was a bit late yesterday so I copied the wrong function call into the switch, the "real" one makes more sense ;-) . Nevertheless I'll go with the suggested else if loop. What is the official source of the c++ standard you quoted? – Lumpi Feb 28 '11 at 20:01
  • 1
    @Lumpi the ISO C++ standard, I purchased a copy some time ago. – Sam Miller Feb 28 '11 at 20:08
  • 2
    @SamMiller : Can you please explain in simpler terms why braces is required in certain switch cases. I was creating a new object in one of the switch case and I got compiler error however if I declare or initialize a normal variable say int. I do not get any error. – tanz Jan 06 '15 at 15:01
  • Technically if and else are also goto in disguise. Or for that mater all control statements are goto in disguise (as they turn to jmp in assembly) .But, since you are using braces, it has the same effect of placing braces around the case statements. – rxantos May 22 '17 at 11:21
18

a switch is essentially a goto, that is, it is a goto to the appropriate label. The C++ standard forbids a goto to bypass an initialization of a non-POD object. Take the vector declaration into braces and it will solve the problem

switch (retrycancel)
    {
     case 4:                //The user pressed RETRY
     {
        std::vector<MainHandles::window_data> windows = MainHandles().enum_windows().get_results(); //Enumerate all visible windows and store handle and caption in "windows"
        break;
     }
    case 2: 
        //code
    }
Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • Thank you! As you mentioned, it is a goto and as I'm trying to learn some proper programming I think I'll go with the if else if block suggested by Sam Miller. – Lumpi Feb 28 '11 at 19:57