【问题标题】:Jump bypasses variable initialization in switch statement跳转绕过switch语句中的变量初始化
【发布时间】:2020-08-25 17:29:30
【问题描述】:

出于某种目的,我的开关盒中需要一个std:: vector<char>std:: string。因此,我编写了以下虚拟代码以查看它是否有效:

#include <iostream>
#include <string>
int main() {
    int choice = 0;

    do {
        std:: cout << "Enter Choice" << std::endl;
        std:: cin >> choice;

        switch(choice) {
            case 1:
                std::cout << "Hi";
                break;

            case 2:
                std::string str;
                std::cin >> str;
                break;

            case 3: //Compilation error, Cannot jump from switch statement to this case label
                std::cout << "World" << std:: endl;
                break;

            default:
                std:: cout << "Whatever" << std:: endl;
        }

    } while(choice != 5);
    return 0;
}

好的,我知道strstd:: string 类型的对象。所以,我试图跳过这个变量初始化。

那为什么定义C风格的字符串不会导致编译错误:

#include <iostream>
#include <string>
int main() {
    int choice = 0;

    do {
        std:: cout << "Enter Choice" << std::endl;
        std:: cin >> choice;

        switch(choice) {
            case 1:
                std::cout << "Hi";
                break;

            case 2:
                char str[6];
                std::cin >> str;
                break;

            case 3:
                std::cout << "World" << std:: endl;
                break;

            default:
                std:: cout << "Whatever" << std:: endl;
        }

    } while(choice != 5);
    return 0;
}

我怎样才能使第一个代码工作?

【问题讨论】:

    标签: c++ arrays string char switch-statement


    【解决方案1】:

    只需使用一对额外的大括号为变量创建一个新块

            case 2:
            { // <-- start new block for str
                std::string str;
                std::cin >> str;
                break;
            } // <-- end of block, str will be destroyed here
    

    【讨论】:

    • 只有在作用域内的字符串是什么意思?大括号之后就不能再使用了。
    • 我认为这是意图,否则为什么要在 switch 语句中声明它?
    • 我想值得添加一个提示,即变量应该在其最内部的范围内声明,它最多只能跨越预期的生命周期。在某些情况下,为明确定义的变量生命周期添加额外的范围甚至很有用。 (例如,它推荐用于锁守卫或其他 RAII 事件。)
    【解决方案2】:

    char str[6]; 是默认初始化的。对于具有自动存储持续时间(“在堆栈上分配”)的简单值的 C 数组,这意味着“根本没有初始化”,所以我想这不是错误。

    但是,如果您像 char str[6] = {} 这样初始化数组,则会产生错误。

    我建议您添加额外的花括号,以便 str 在其自己的范围内,并且在进一步的 case 语句中不可见:

    #include <iostream>
    #include <string>
    int main() {
        int choice = 0;
    
        do {
            std:: cout << "Enter Choice" << std::endl;
            std:: cin >> choice;
    
            switch(choice) {
                case 1:
                    std::cout << "Hi";
                    break;
    
                case 2: {  // Changed here
                    std::string str;
                    std::cin >> str;
                    break;
                }
                case 3: // `str` is not available here, no compilation error
                    std::cout << "World" << std:: endl;
                    break;
    
                default:
                    std:: cout << "Whatever" << std:: endl;
            }
    
        } while(choice != 5);
        return 0;
    }
    

    在哪里放置括号是一种样式偏好。

    【讨论】:

    • str 不能在作用域的大括号后使用。输入字符串不能再使用是什么意思?
    • 这是一个小例子。它也没有在原始代码中使用。但是可以在switch 语句中完成choice == 2 所需的所有处理:调用函数、将str 推送到vectors 等。如果您需要在switch 语句之后严格访问str,这是一个气味:不能保证str 通常在switch 之后会有一个合理的值。
    猜你喜欢
    • 1970-01-01
    • 2016-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-12
    • 2014-01-13
    • 1970-01-01
    • 2018-04-28
    相关资源
    最近更新 更多