简体   繁体   English

C++ primer第5版开关声明

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

In C++ primer 5th edition the solutions appendix, gives an example about 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.

But I think it is wrong because file_name has been implicitly initialized and that is why the compiler flags that error.但我认为这是错误的,因为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;
}

So are my guesses correct?那么我的猜测是否正确?

The term "implicit initialization" sounds technical. “隐式初始化”一词听起来很专业。 But it's gobbledygook.但这是官话。 It means nothing .没有任何意义

And the compiler doesn't use this made-up term either .而且编译器也不使用这个虚构的术语。 To wit:以机智:

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;
    }
}

Compiler output:编译器 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;
      |                 ^

And that's all.就这样。 Initialization, plain and simple.初始化,简单明了。 When you remove the initializer for the member Foo::a , there's no more initialization, and the compiler will be OK with that:当您删除成员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
    }
}

Now, fa is not initialized, and that's OK unless you attempt to use its value.现在, fa没有被初始化,这没关系,除非你试图使用它的值。 The access to fa doesn't cause a compile-time failure, but is undefined behavior, just as-if you wrote the following:fa的访问不会导致编译时失败,而是未定义的行为,就像您编写了以下内容一样:

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

Modern compilers can and will use the uninitialized variable/member access as an optimization hint.现代编译器可以并且将会使用未初始化的变量/成员访问作为优化提示。 The code that uses the uninitialized value may be removed, for example.例如,可以删除使用未初始化值的代码。

According for example to the C++ 17 Standard (9.7 Declaration statement)例如根据C++ 17标准(9.7声明声明)

3 It is possible to transfer into a block, but not in a way that bypasses declarations with initialization. 3 可以转移到块中,但不能以绕过初始化声明的方式进行。 A program that jumps91 from a point where a variable with automatic storage duration is not in scope to a point where it is in scope is ill-formed unless the variable has scalar type, class type with a trivial default constructor and a trivial destructor, a cv-qualified version of one of these types, or an array of one of the preceding types and is declared without an initializer从具有自动存储持续时间的变量不在 scope 中的点跳转 91 到它在 scope 中的点的程序是格式错误的,除非该变量具有标量类型,class 类型,具有平凡的默认构造函数和平凡的析构函数,a这些类型之一的 cv 限定版本,或上述类型之一的数组,并且在没有初始化程序的情况下声明

The class std::string does not has a trivial default constructor and a trivial destructor. class std::string没有平凡的默认构造函数和平凡的析构函数。

In this code snippet在此代码段中

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

the class Foo has a trivial default constructor and a trivial destructor. class Foo 有一个平凡的默认构造函数和一个平凡的析构函数。

and for example (15.1 Constructors)例如(15.1 构造函数)

6 A default constructor is trivial if it is not user-provided and if: 6 如果不是用户提供的默认构造函数是微不足道的,并且:

(6.1) — its class has no virtual functions (13.3) and no virtual base classes (13.1), and (6.1) — 它的 class 没有虚函数 (13.3) 也没有虚基类 (13.1),并且

(6.2) — no non-static data member of its class has a default member initializer (12.2), and (6.2) — 其 class 的非静态数据成员均没有默认成员初始值设定项 (12.2),并且

(6.3) — all the direct base classes of its class have trivial default constructors, and (6.3) — 其 class 的所有直接基类都有平凡的默认构造函数,并且

(6.4) — for all the non-static data members of its class that are of class type (or array thereof), each such class has a trivial default constructor. (6.4) — 对于其 class 的所有非静态数据成员 class 类型(或其数组),每个这样的 class 都有一个普通的默认构造函数。

Otherwise, the default constructor is non-trivial.否则,默认构造函数是不平凡的。

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

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