乐趣区

关于c++:c-error-crosses-initialization-of-问题探究

最近在写代码的时候,碰到了 crosses initialization of … 的问题,只因我在 switch 的某个 case 分支下定义了一个变量,于是乎便将这个问题整顿一下。

1 switch case 的某个分支下定义了变量

switch case 是咱们在工作中常见的分支语句,如果在某个分支下不失当的应用了局部变量,就有可能呈现本文提到的问题。

1.1 问题代码示例

#include <iostream>

void switchTest(int code);

int main() {switchTest(1);
}

void switchTest(int code) {switch (code) {
    case 1:
        int myNum = 0;
        break;
    case 2:
        break;
    default:
        break;
    }
}

上述代码,我在第一个 case 分支下定义了 myNum 变量,尝试编译,呈现如下谬误。次要看 C2360 这一行,myNum 的初始化操作由 case 标签跳过,也就是说当 code !=1 的时候,不会进行 myNum 的初始化。第一反馈是“我这个 myNum 只在 case 1 下用啊,不初始化就不初始化嘛,反正其余中央又不必”。

呃,这就牵扯到变量的作用范畴了。myNum 这个局部变量的作用范畴是从定义处开始直到 switch 语句完结 。艰深说, 就算咱们跳过了 case 1 处的初始化,myNum 在前面的分支中,也是能够被拜访到的,被拜访到就有可能被应用(尽管咱们本人没打算在前面应用,但编译器认为这是有危险的),然而咱们又没有对其进行初始化,那这就会出问题。那这个问题怎么解决呢?

1.2 问题的解决

办法一、限定 myNum 的作用域

void switchTest(int code) {switch (code)
    {
    case 1:
    {
        int myNum = 0;
        break;
    }
    case 2:
        break;
    default:
        break;
    }
}

咱们给 case 1 加上大括号,明确通知编译器,它只在 case 1 里无效,咱们在前面不应用这个 myNum 了,这种形式应该是最合乎咱们本意的,编译失常通过。

办法二、提前 myNun 的初始化

void switchTest(int code) {
    int myNum = 0;
    switch (code)
    {
    case 1:
        break;
    case 2:
        break;
    default:
        break;
    }
}

既然 myNum 不被初始化的起因的是在 case 分支里定义了局部变量,那么咱们将 myNum 的初始化提到 switch 里面吧,这样一来,在它的作用域内,myNum 就必定会被初始化了,上述问题也同样不会产生了。这样尽管解决了问题,但却扩充了变量的作用范畴。如果咱们确定只在某个分支下应用这个变量,这种计划就不太可取。

办法三、将用到该变量的分支放到最初,且去掉 default 分支

void switchTest(int code) {switch (code)
    {
    case 2:
        break;
    case 1:
        int myNum = 0;
        break;
    }
}

下面这种写法是能编译过的,而且满足我的用意。我把 case 1 放到了最初一个分支,这样一来,myNum 的作用域就只是在最初一个分支了,在 myNum 的作用域内,它都是被初始化了的,因而是不会出问题的 。当然,这样写只是为了阐明,呈现这个谬误的根因是: 变量在其作用范畴内,可能不会被初始化。(我的项目中请勿这样操作,一不小心就是一口大锅)

2 goto 跳过了变量的初始化

goto 语句的使用率并不高,但应用出 bug 的概率却极高。

2.1 问题代码示例

#include <iostream>

void gotoTest();

int main()
{gotoTest();
}

void gotoTest() {
    goto label;
    int myNum = 1;
    label: std::cout << "goto the label" << std::endl;
}

下面的代码里,咱们应用 goto 跳过了 myNum 的初始化,不出意外的出了意外,编译时呈现如下谬误,起因和咱们下面 switch 的例子是一样的,那解决办法自热也是相似的。

2.2 问题的解决

办法一、限定 myNum 的作用域

void gotoTest() {
    goto label;
    {int myNum = 1;}
    label: std::cout << "goto the label" << std::endl;
}

限度 myNum 的作用域,通知编译器咱们在前面不应用了。

办法二、提前 myNun 的初始化

void gotoTest() {
    int myNum = 1;
    goto label;
    label: std::cout << "goto the label" << std::endl;
}

将 myNum 的初始化提前,确保不会因为 goto 导致跳过了初始化。

3 论断

crosses initialization of 翻译过去就是 跳过了初始化 ,根本原因是变量在其作用范畴内,存在不被初始化的危险,解决思路有两个: 一是明确限定变量的作用域;而是将初始化提前,防止不被初始化的产生

退出移动版