繁体   English   中英

C++ primer第5版开关声明

[英]C++ primer 5th edition switch statement

在C++ primer 5th edition the solutions appendix中,给出了一个关于switch语句的例子:

 case true: string file_name; // error: control bypasses an implicitly initialized variable. ... case false: if(file_name.empty()); // file_name is in scope but wasn't initialized.

但我认为这是错误的,因为file_name已被隐式初始化,这就是编译器标记该错误的原因。

struct Foo{};
switch(val){
    case 1:
       Foo f; // ok not-implicitly initialized like std::string
    break;
    case 2:
        f.some_member(); // use f;
}

那么我的猜测是否正确?

“隐式初始化”一词听起来很专业。 但这是官话。 没有任何意义

而且编译器也不使用这个虚构的术语。 以机智:

int main()
{
    struct Foo {
        void some_member() {}
        int a = 1;
    };
    int val = 0;
    switch (val){
        case 1:
            Foo f;
            break;
        case 2:
            f.some_member(); // use f;
    }
}

编译器 output:

<source>: In function 'int main()':
<source>:12:14: error: jump to case label
   12 |         case 2:
      |              ^
<source>:10:17: note:   crosses initialization of 'main()::Foo f'
   10 |             Foo f;
      |                 ^

就这样。 初始化,简单明了。 当您删除成员Foo::a的初始值设定项时,将不再进行初始化,并且编译器可以接受:

int main()
{
    struct Foo {
        void some_member() {}
        int a;
    };
    int val = 0;
    switch (val){
        case 1:
            Foo f; // OK - no initialization at all
            break;
        case 2:
            f.some_member(); // use f
            if (f.a) {};     // undefined behavior, a is uninitialized here
    }
}

现在, fa没有被初始化,这没关系,除非你试图使用它的值。 fa的访问不会导致编译时失败,而是未定义的行为,就像您编写了以下内容一样:

int main() {
   int a;
   if (a) {} // undefined behavior, a isn't initialized
}

现代编译器可以并且将会使用未初始化的变量/成员访问作为优化提示。 例如,可以删除使用未初始化值的代码。

例如根据C++ 17标准(9.7声明声明)

3 可以转移到块中,但不能以绕过初始化声明的方式进行。 从具有自动存储持续时间的变量不在 scope 中的点跳转 91 到它在 scope 中的点的程序是格式错误的,除非该变量具有标量类型,class 类型,具有平凡的默认构造函数和平凡的析构函数,a这些类型之一的 cv 限定版本,或上述类型之一的数组,并且在没有初始化程序的情况下声明

class std::string没有平凡的默认构造函数和平凡的析构函数。

在此代码段中

struct Foo{};
switch(val){
    case 1:
       Foo f; // ok not-implicitly initialized like std::string
    break;
    case 2:
        f.some_member(); // use f;
}

class Foo 有一个平凡的默认构造函数和一个平凡的析构函数。

例如(15.1 构造函数)

6 如果不是用户提供的默认构造函数是微不足道的,并且:

(6.1) — 它的 class 没有虚函数 (13.3) 也没有虚基类 (13.1),并且

(6.2) — 其 class 的非静态数据成员均没有默认成员初始值设定项 (12.2),并且

(6.3) — 其 class 的所有直接基类都有平凡的默认构造函数,并且

(6.4) — 对于其 class 的所有非静态数据成员 class 类型(或其数组),每个这样的 class 都有一个普通的默认构造函数。

否则,默认构造函数是不平凡的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM