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

How to initialize a struct to 0 in C++

这是一个相关的 C 答案,它在 C++ 中不起作用(作为结构的零初始值设定项):Initializing a struct to 0。提出的解决方案之一是:

myStruct _m1 = {0}; 

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

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

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

相关:

  1. 正在初始化 C 中为 0 的结构:Initializing a struct to 0
  2. 更新:(一个相邻但不重复的问题,结果也非常有用)

另请参阅:

  1. [相邻相关,但用于 C 样式数组,不是 结构] How to initialize all members of an array to the same value?

致投票结束此问题的人:

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

我问的后续问题:

开始之前:

  1. 让我指出很多关于此语法的混淆是因为在 C 和 C++ 中你 可以 使用 = {0} 语法来将 C 风格 数组 所有成员初始化为零! 请参阅此处:https://en.cppreference.com/w/c/language/array_initialization。这有效:

    int z[3] = {0}; // z has type int[3] and holds all zeroes
    

    但是,该语法 not 对于 structs 的工作方式与 C 风格数组完全不同。

  2. 另请参阅我在下面写下此答案后提出的后续问题:


返回答案:

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

# does NOT work
myStruct _m1 = {0}; 

# works!
myStruct _m1 = {};

现在可以编译了。但是,我 运行 进行了一系列测试以检查 struct_initialization.cpp file in my eRCaGuy_hello_world repo, and that does NOT initialize all elements of the struct to zero! Rather, it initializes the struct to its default values. To run my tests and see for yourself, clone my repo above and run eRCaGuy_hello_world/cpp/run_struct_initialization.sh.

中的一些内容

假设你有这个结构:

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

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

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

所以请忽略我不必要地使用 typedef 来定义下面的结构。

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

data_t d2 = {};
printf("d2.num1 = %i\nd2.num2 = %i\nd2.num3 = %i\nd2.num4 = %i\n\n",
       d2.num1, d2.num2, d2.num3, d2.num4);

...输出将是:

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

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

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

myStruct _m1{};

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

data_t d2{};
printf("d2.num1 = %i\nd2.num2 = %i\nd2.num3 = %i\nd2.num4 = %i\n\n",
       d2.num1, d2.num2, d2.num3, d2.num4);

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

即使在将结构设置为 = {0} 的情况下也有效,例如:

// 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\nd3.num2 = %i\nd3.num3 = %i\nd3.num4 = %i\n\n",
       d3.num1, d3.num2, d3.num3, d3.num4);

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

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

在 C 风格 数组 上,但是(不是结构),这些语义工作正常。请在此处参考此答案 (How to initialize all members of an array to the same value?)。因此,以下几行在使用 C++ 时都将 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)

所以,after much experimentation,看起来以下几种方法是零初始化结构 PERIOD 的唯一方法。如果你有不同的理解,请评论and/or在这里留下你自己的答案。

在 C++ 中对结构进行零初始化的唯一可能方法是:

  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};
    
  2. 使用memset()强制所有字节为零:

     data_t d3;
     memset(&d3, 0, sizeof(d3));
    
  3. 首先将所有默认值设置为零:

     // 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};
    
  4. 为 C++ 结构编写构造函数

     // 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
    
  5. 使用没有默认值的结构,并从中创建您的对象static

     typedef 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;
    
  6. 因此,如果您有一个具有 非零 默认值的结构,并且您想要将所有值归零,则必须明确执行!这里还有一些方法:

     // 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();
    

这里最大的收获是其中的 NONE:data_t d{}data_t d = {}data_t d = {0},实际上将结构的所有成员设置为零!

  1. data_t d{} 将所有值设置为其在结构中定义的默认值。
  2. data_t d = {} 还将所有值设置为其默认值。
  3. 并且 data_t d = {0} 仅将第一个值设置为零,将所有其他值设置为默认值。

所以,要明确

请注意,我写的上述要点似乎与下面列出的 this documentation on cppreference.com, so it has led me to ask 相矛盾,事实证明这对我的理解非常有帮助!

更进一步

  1. 最有用我的后续问题:

参考文献:

  1. 非常有用:
    1. https://en.cppreference.com/w/cpp/language/zero_initialization
    2. https://en.cppreference.com/w/cpp/language/aggregate_initialization
    3. https://en.cppreference.com/w/cpp/language/value_initialization
  2. 非常有用:将 array(不是结构)的所有成员初始化为相同的值:
    1. How to initialize all members of an array to the same value?
    2. [仅限 gcc] How to initialize all members of an array to the same value?
  3. https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/blob/master/cpp/struct_initialization.cpp
    1. 克隆此 repo 并 运行 使用 cpp/run_struct_initialization.sh
    2. 自己编写代码

相关:

  1. Initializing default values in a struct
  2. *****[我自己的回答,它演示了这种结构 modification/aggregate 成员在任何函数中的重新分配:leds[0] = {10, 20, 30, 40, 50};] Arduino Stack Exchange: Initializing Array of structs

一般来说这是不可能的。 class 可能无法提供访问所有成员的方法,在这种情况下,你能做的最好的事情就是 value initialize 它会给你一个 class.[=11= 的默认版本]

C++ 中的对象能够控制其中任何子对象的值。因此,C++ 没有强制对任何对象进行零初始化的机制一般

没有用户提供的构造函数或默认成员初始值设定项的对象可以在两种情况下进行零初始化:如果声明变量 static,或者如果对象正在被值初始化。有多种语法会引发对象的值初始化,包括 T()T{}T t = {};,如果适用的话。

但除此之外,如果对象类型的创建者不希望它被零初始化,那么你不能将其强加给对象。您可以请求值初始化或默认初始化,但是这两者是否会调用零初始化取决于类型。

在 C++ 中,对于没有限制器的类型(id est trivially constructible),{} 总是将所有字节初始化为零,与 C 中的 { 0 } 相同。

PlainOldData pod{};

对于具有构造函数的类型,因此不易构造,将所有字节初始化为零毫无意义,因为这些对象旨在控制它们自己的状态。你通常想要的是默认初始化,通常可以用 {}.:

Object obj{};
// or
Object obj;

您可以绕过此限制并使用 memset 清除内存,但请注意它 导致覆盖 vtable 指针等的很多问题等等。

memset(&obj, 0, sizeof obj); // dangerous for non-trivial objects