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

2021-12-23 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/language/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. 明确:

 // 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() 强制所有字节为零:

     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},其实就是把一个struct的所有成员都设置为零!

    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} 仅将第一个值设置为零,并将所有其他值设置为其默认值.
    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. [非常有用] 将数组(不是结构)的所有成员初始化为相同的值:
    7. 如何将数组的所有成员初始化为相同的值?
    8. [gcc only] 如何将数组的所有成员初始化为相同的值?
    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:初始化结构数组

    相关文章