如何在 C++ 中将结构初始化为 0

2022-01-18 00:00:00 initialization struct c++

这是一个在 C++ 上不起作用的相关 C 答案(作为结构的零初始化器):将结构初始化为 0.提出的解决方案之一是:

Here is a related C answer that doesn't work (as a zero initializer for a struct) on C++: Initializing a struct to 0. One of the solutions presented is this:

myStruct _m1 = {0}; 

这在 C 中工作正常,但在 C++ 中不起作用.:( :

This works fine in C, but it doesn't work in C++. :( :

错误:无法使用int"类型的右值初始化myScope::MyStruct"类型的成员子对象.

error: cannot initialize a member subobject of type 'myScope::MyStruct' with an rvalue of type 'int'`.

如何在 C++ 中对结构进行零初始化?

How do you zero-initialize a struct in C++?

  1. 正在初始化在 C 中将结构体设置为 0:将结构体初始化为 0
  2. 更新:(一个相邻但不重复的问题,结果也非常有用)用空花括号初始化

致投票结束这个问题的模组:

我的问题与其他问题不重复(用空花括号初始化),因为另一个问题不是询问在 C++ 中初始化结构的各种方法以及为什么 C 方式不起作用,而是在问 为什么 C++ 关键字 explicit 破坏他们的一种初始化技术.两个截然不同的问题.不重复.

To the mods voting to close this question:

My question is not a duplicate of this other question (Initialization with empty curly braces), as this other question isn't asking about the various ways to initialize a struct in C++ and why the C way doesn't work, rather, they are asking why does the C++ keyword explicit break one of their initialization techniques. Two distinct questions. Not duplicate.

推荐答案

我想通了:要让它编译,只需删除零即可:

I figured it out: to get it to compile, just delete the zero:

myStruct _m1 = {};

现在可以编译了.然而,我跑了一堆测试来检查一些东西,这不会将结构的所有元素初始化为零!相反,它将结构初始化为其默认值.

It now compiles. However, I ran a bunch of tests to check some things, and this does NOT initialize all elements of the struct to zero! Rather, it initializes the struct to its default values.

假设你有这个结构:

typedef struct
{
    int num1 = 100;
    int num2 = -100;
    int num3;
    int num4 = 150;
} data_t;

注意:上面的 typedef 是我在 C 而不是 C++ 中测试这些东西时遗留下来的(当然,默认的结构值在 C 中是不允许的).对于 C++,这是首选:

Note: the typedef above is a carry-over from when I was testing this stuff in C instead of C++ (although the default struct values are not allowed in C, of course). For C++, this is preferred instead:

struct data_t
{
    int num1 = 100;
    int num2 = -100;
    int num3;
    int num4 = 150;
};

所以在我不必要地使用 typedef 来定义下面的结构时,请忽略它.

So please ignore it wherever I unnecessarily use typedef to define the structs below.

无论如何,如果我声明上述 data_t 结构之一,然后执行此操作:

Anyway, if I declare one of the above data_t structs, and then do this:

data_t d2 = {};
printf("d2.num1 = %i
d2.num2 = %i
d2.num3 = %i
d2.num4 = %i

",
       d2.num1, d2.num2, d2.num3, d2.num4);

...输出将是:

d2.num1 = 100
d2.num2 = -100
d2.num3 = 0
d2.num4 = 150

我什至不确定 d2.num3 是否为零,因为它被初始化为零,或者因为它未初始化,而那个内存位置恰好包含零.

And I'm not even sure if d2.num3 is zero because it was initialized to zero or because it was left uninitialized, and that memory location happened to contain zero.

如此处所述:https://en.cppreference.com/w/cpp/语言/zero_initialization,你也可以这样做:

As explained here: https://en.cppreference.com/w/cpp/language/zero_initialization, you can also do this:

myStruct _m1{};

在上面的例子中,这段代码:

In the example above, this code:

data_t d2{};
printf("d2.num1 = %i
d2.num2 = %i
d2.num3 = %i
d2.num4 = %i

",
       d2.num1, d2.num2, d2.num3, d2.num4);

...会产生与我上面显示的相同的输出.

...would produce output identical to what I showed above.

即使将结构设置为 = {0} 确实有效,例如:

Even in cases where setting the struct to = {0} DOES work, such as this:

// Does NOT do what I expected! Only sets the FIRST value in the struct to zero! 
// The rest seem to use default values.
data_t d3 = {0};
printf("d3.num1 = %i
d3.num2 = %i
d3.num3 = %i
d3.num4 = %i

",
       d3.num1, d3.num2, d3.num3, d3.num4);

...输出仍然不是我所期望的,因为它只是将 first 值设置为零!(我不明白为什么):

...the output is still not what I expected, as it only sets the first value to zero! (I don't understand why):

d3.num1 = 0
d3.num2 = -100
d3.num3 = 0
d3.num4 = 150

然而,在 C 风格的数组(不是结构)上,这些语义可以正常工作.在此处参考此答案(如何将数组的所有成员初始化为相同的值?).因此,在使用 C++ 时,以下几行都将 C 样式数组的所有元素都设置为零:

On C-style arrays, however (NOT structs), these semantics work fine. Refer to this answer here (How to initialize all members of an array to the same value?). The following lines, therefore, both set all elements of the C-style array to zero when using C++:

uint8_t buffer[100] = {0}; // sets all elements to 0 in C OR C++
uint8_t buffer[100] = {};  // sets all elements to 0 in C++ only (won't compile in C)

所以,经过大量实验,它看起来以下几种方法是对结构 PERIOD 进行零初始化的唯一方法.如果您有不同的看法,请在此处发表评论和/或留下您自己的答案.

So, after much experimentation, it looks like the following several ways are the ONLY ways to zero-initialize a struct, PERIOD. If you know differently, please comment and/or leave your own answer here.

  1. 要明确:

  1. Be explicit:

 // C-style typedef'ed struct
 typedef struct
 {
     int num1 = 100;
     int num2 = -100;
     int num3;
     int num4 = 150;
 } data_t;

 // EXPLICITLY set every value to what you want!
 data_t d1 = {0, 0, 0, 0};
 // OR (using gcc or C++20 only)
 data_t d2 = {.num1 = 0, .num2 = 0, .num3 = 0, .num4 = 0}

  • 使用 memset() 将所有字节强制为零:

  • Use memset() to force all bytes to zero:

     data_t d3;
     memset(&d3, 0, sizeof(d3));
    

  • 首先将所有默认值设置为零:

  • Set all default values to zero in the first place:

     // C-style typedef'ed struct
     typedef struct
     {
         int num1 = 0;
         int num2 = 0;
         int num3 = 0;
         int num4 = 0;
     } data_t;
    
     // Set all values to their defaults, which are zero in
     // this case
     data_t d4 = {};
     // OR
     data_t d5{}; // same thing as above in C++
    
     // Set the FIRST value only to zero, and all the rest
     // to their defaults, which are also zero in this case
     data_t d6 = {0};
    

  • 为 C++ 结构编写构造函数

  • Write a constructor for the C++ struct

     // 1. Using an initializer list
     struct data
     {
         int num1;
         int num2;
         int num3;
         int num4;
    
         data() : 
             num1(0),
             num2(0),
             num3(0),
             num4(0) {}
     };
    
     data d7; // all values are zero
    
     // OR: 2. manually setting the values inside the constructor
     struct data
     {
         int num1;
         int num2;
         int num3;
         int num4;
    
         data()
         {
             num1 = 0;
             num2 = 0;
             num3 = 0;
             num4 = 0;
         }
     };
    
     data d8; // all values are zero
    

  • 使用没有默认值的结构,并让你的对象由它创建static

     tpedef struct
     {
         int num1;
         int num2;
         int num3;
         int num4;
     } data_t;
    
     // `static` forces a default initialization of zero for each
     // value when no other default values are set
     static data_t d9;
    

  • 所以,如果你有一个 非零 默认值的结构,并且你想将所有值归零,你必须明确地这样做!这里还有一些方法:

  • So, if you have a struct with non-zero default values, and you want to zero all values, you must do it EXPLICITLY! Here are some more ways:

     // 1. Have a `constexpr` copy of the struct that you use to
     // reset other struct objects. Ex:
    
     struct data
     {
         int num1 = 1;
         int num2 = 7;
         int num3 = -10;
         int num4 = 55;
     };
    
     constexpr data DATA_ALL_ZEROS = {0, 0, 0, 0};
    
     // Now initialize d13 to all zeros using the above `constexpr` struct 
     // object
     data d13 = DATA_ALL_ZEROS; 
    
    
     // OR 2. Use a `zero()` member function to zero the values:
    
     struct data
     {
         int num1 = 1;
         int num2 = 7;
         int num3 = -10;
         int num4 = 55;
    
         zero()
         {
             num1 = 0;
             num2 = 0;
             num3 = 0;
             num4 = 0;
         }
     };
    
     data d14;
     d14.zero();
    

  • 这里最大的收获是这些都没有:data_t d{}data_t d = {}data_t d = {0},实际上将一个结构的所有成员都设置为零!

    The big take-away here is that NONE of these: data_t d{}, data_t d = {}, and data_t d = {0}, actually set all members of a struct to zero!

    1. data_t d{} 将所有值设置为其在结构中定义的默认值.
    2. data_t d = {} 还将所有值设置为其默认值.
    3. 并且 data_t d = {0} 仅将 FIRST 值设置为零,而将所有其他值设置为其默认值.
    1. data_t d{} sets all values to their defaults defined in the struct.
    2. data_t d = {} also sets all values to their defaults.
    3. And data_t d = {0} sets only the FIRST value to zero, and all other values to their defaults.

    所以,明确说明!

    请注意,我写的上述关键要点似乎与 本文档,所以这让我提出了这个后续问题,列在下面的参考文献 #1 中,事实证明这对我的理解非常有帮助!

    Note that the above key take-aways I wrote seem to contradict this documentation, so it has led me to ask this follow-up question, listed as Reference #1 below, which has proven VERY helpful to my understanding!

    1. [最有用] 为什么不将 C++ 结构初始化为 `= {0}` 将其所有成员设置为 0?
    2. [非常有用]
    3. https://en.cppreference.com/w/cpp/language/zero_initialization
    4. https://en.cppreference.com/w/cpp/language/aggregate_initialization
    5. https://en.cppreference.com/w/cpp/language/value_initialization
    6. [非常有用] 将 array(非结构)的所有成员初始化为相同的值:
    7. 如何将数组的所有成员初始化为相同的值?
    8. [仅限 gcc] 如何将数组的所有成员初始化为相同的值?
    9. https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/blob/master/cpp/struct_initialization.cpp
    10. 克隆此 repo 并使用 cpp/run_struct_initialization.sh
    11. 自己运行代码
    1. [MOST USEFUL] Why doesn't initializing a C++ struct to `= {0}` set all of its members to 0?
    2. [VERY USEFUL]
    3. https://en.cppreference.com/w/cpp/language/zero_initialization
    4. https://en.cppreference.com/w/cpp/language/aggregate_initialization
    5. https://en.cppreference.com/w/cpp/language/value_initialization
    6. [VERY USEFUL] Initializing all members of an array (not struct) to the same value:
    7. How to initialize all members of an array to the same value?
    8. [gcc only] How to initialize all members of an array to the same value?
    9. https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/blob/master/cpp/struct_initialization.cpp
    10. Clone this repo and run the code yourself with cpp/run_struct_initialization.sh

    相关:

    1. 初始化结构中的默认值
    2. *****[我自己的答案,它演示了在任何函数中这种结构修改/聚合成员重新分配:leds[0] = {10, 20, 30, 40, 50};] Arduino Stack Exchange:初始化结构数组

    相关文章