在调用函数时切换"控制转移绕过初始化:"

Lum*_*mpi 52 c++ function switch-statement

当我尝试构建以下开关时,我得到"转移控制绕过初始化:"错误:

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
}
Run Code Online (Sandbox Code Playgroud)

它与我调用枚举函数有关.如果不允许从交换机内调用函数,是否有针对此类问题的解决方法?

Sam*_*ler 78

C++标准的第6.6.4节:

goto语句无条件地将控制转移到标识符标记的语句.标识符应为位于当前函数中的标签(6.1).

C++标准的第6.7节:

可以转换为块,但不能以初始化绕过声明的方式.从具有自动存储持续时间的局部变量不在范围内的点跳转到其在范围内的点的程序是不正确的,除非变量具有POD类型(3.9)并且在没有初始化程序的情况下声明

强调我加入了.既然switch真的goto是伪装,你就会遇到这种行为.要解决此问题,请添加大括号(如果必须使用)switch

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

或重构成if/else

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

虽然对我来说并不是很明显你希望通过创建windows vector内部来实现什么switch,所以你可能想重新考虑你的设计.注意我添加了const限定符,windows因为它没有在您的示例中修改.

  • @SamMiller:您能否用更简单的术语解释一下为什么在某些开关情况下需要大括号。我正在其中一个 switch case 中创建一个新对象,但如果我声明或初始化一个普通变量(如 int),则会出现编译器错误。我没有收到任何错误。 (2认同)

Arm*_*yan 11

一个开关本质上是一个goto,也就是说,它是一个goto适当的标签.C++标准禁止goto绕过非POD对象的初始化.将矢量声明带入括号,它将解决问题

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
    }
Run Code Online (Sandbox Code Playgroud)