繁体   English   中英

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

[英]How to initialize a struct to 0 in C++

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

myStruct _m1 = {0}; 

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

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

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

有关的:

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

也可以看看:

  1. [相邻相关,但适用于 C 风格 arrays,而不是结构]如何将数组的所有成员初始化为相同的值?

对于投票结束这个问题的人:

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

我问的后续问题:

  1. 为什么不将 C++ 结构初始化为= {0}将其所有成员设置为 0?

在我们开始之前:

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

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

    但是,该语法对于structs的工作方式不同,它们与 C 风格的 arrays 完全不同。

  2. 另请参阅我在下面写完此答案后提出的后续问题:为什么不将 C++ 结构初始化为= {0}将其所有成员设置为 0?


回到答案:

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

# does NOT work
myStruct _m1 = {0}; 

# works!
myStruct _m1 = {};

它现在编译。 但是,我运行了一堆测试来检查我的eRCaGuy_hello_world存储库中的struct_initialization.cpp文件中的一些内容,这并没有将结构的所有元素初始化为零,而是将结构初始化为其默认值 要运行我的测试并亲自查看,请在上面克隆我的 repo 并运行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++ 中测试这些东西时遗留下来的(当然,在 Z0D61F8370CAD1D412F80ZB84D143E1257 中不允许使用默认结构值)。 对于 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);

... output 将是:

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

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

如此处所述: 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);

...会产生与我上面显示的相同的 output。

即使在将结构设置为= {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);

... output 仍然不是我所期望的,因为它只将第一个值设置为零:(我不明白为什么):

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

然而,在 C 风格的arrays上(不是结构),这些语义可以正常工作。 请在此处参考此答案( 如何将数组的所有成员初始化为相同的值? )。 因此,在使用 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)

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

在 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. 使用没有默认值的结构,并让您的 object 从中创建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();

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

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

所以,要明确

请注意,我写的上述关键要点似乎与cppreference.com 上的文档相矛盾,因此我提出了下面列出的后续问题,这对我的理解非常有帮助!

走得更远

  1. 最有用我的后续问题:为什么不将 C++ 结构初始化为= {0}将其所有成员设置为 0?

参考:

  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. 非常有用:将数组(不是结构)的所有成员初始化为相同的值:
    1. 如何将数组的所有成员初始化为相同的值?
    2. [仅限 gcc] 如何将数组的所有成员初始化为相同的值?
  3. https://github.com/ElectricRCAaircraftGuy/eRCaGuy_hello_world/blob/master/cpp/struct_initialization.cpp
    1. 克隆这个 repo 并使用cpp/run_struct_initialization.sh自己运行代码

有关的:

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

一般是不可能的。 class 可能无法提供访问所有成员的方法,在这种情况下,您可以做的最好的事情是初始化它,这将为您提供该 class 的默认版本。

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

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

但除此之外,如果 object 类型的创建者不希望它被零初始化,那么您不能将其强加于 object。 您可以要求值初始化或默认初始化,但其中任何一个是否会调用零初始化取决于类型。

在 C++ 中,对于没有收缩器的类型(id est 可轻松构造), {}始终将所有字节初始化为零,与 C 中的{ 0 }相同。

PlainOldData pod{};

对于具有构造函数的类型,因此不是简单可构造的,将所有字节初始化为零几乎没有意义,因为这些对象旨在控制它们自己的 state。 您通常想要的是默认初始化,通常可以使用{}来完成。:

Object obj{};
// or
Object obj;

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

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

暂无
暂无

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

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