【问题标题】:Default initialization of C++ Member arrays?C++成员数组的默认初始化?
【发布时间】:2011-10-13 20:53:23
【问题描述】:

这是一个简单的问题,但我似乎找不到明确的答案。

如果我们有以下类:

class Test
{
...
  char testArray[10];

...
}; 

当我们创建Test实例时,testArray[1]的默认值是多少?

如果它是一个本地数组,它将是未初始化的。
如果是静态数组,则初始化为0。

当数组是类成员时它会做什么?

【问题讨论】:

  • 这取决于类定义的其余部分,包括任何构造函数的定义以及可能如何实例化类实例。请显示更多代码。
  • “班级成员”是什么意思?您在 C++ 中显示的示例testArray 属于实例,而不属于类。要让它属于该类,您需要将其设为static,并在其他地方定义它。
  • @KarlKnechtel:卢西亚诺完全正确地使用了这个词。 testArray 是类的非静态数据成员。 “类的成员是数据成员、成员函数 (9.3)、嵌套类型和枚举器。数据成员和成员函数是静态或非静态的;参见 9.4。”
  • Charles:假设Test的构造函数没有给testArray赋值。
  • @CharlesBailey:不是这样。如果构造函数提供了一个初始化器,那么它就不会是 default-initialized,而是“什么构成数组成员的 default-initialization?”仍然是一个有效的问题。

标签: c++


【解决方案1】:

来自标准,第 8.5 节 [dcl.init]

默认初始化T 类型的对象意味着:

  • 如果 T 是(可能是 cv 限定的)类类型(第 9 条),则调用 T 的默认构造函数(如果 T 没有可访问的默认值,则初始化格式错误构造函数);

  • 如果T是数组类型,每个元素都是默认初始化的

  • 否则,不执行初始化。

还有第 12.6.2 节 [class.base.init]:

在非委托构造函数中,如果给定的非静态数据成员或基类没有由 mem-initializer-id 指定(包括没有 mem -initializer-list 因为构造函数没有ctor-initializer)并且实体不是抽象类(10.4)的虚拟基类,那么

  • 如果实体是具有 brace-or-equal-initializer 的非静态数据成员,则实体按照 8.5 中的规定进行初始化;
  • 否则,如果实体是变体成员 (9.5),则不执行初始化;
  • 否则,实体会默认初始化 (8.5)。

所以因为元素类型是char,所以当每个元素default-initialized时,不会进行初始化。内容保留任意值。

当然,除非它是类实例的成员,并且该实例具有静态存储持续时间。然后整个实例零初始化,数组成员和所有,在执行开始之前。

【讨论】:

  • 那么如果我理解正确的话,值不会被默认初始化,除非Test类的实例是静态实例?
  • @Luciano:不,如果构造函数没有为它指定初始化程序(包括启用聚合初始化的隐式构造函数),它将被默认初始化。 char[] 的默认初始化是无操作的。如果实例具有静态存储持续时间,那么之前是零,所以在无操作之后,它仍然是零。在其他情况下,内存中的任何内容都将决定该值。
  • @BenVoigt 这个规则可以应用于静态数组吗?如果我们定义一个局部 int,它将有一个随机值,但如果我们定义一个静态 int,它将被设置为 0。静态数组是否具有相同的行为?可以在这里找到一个讨论:stackoverflow.com/q/2091499/440403
  • @camino:没有初始化的本地不是“随机”值,它是一个不确定的值。区别很重要,而且真的搞砸了密码学软件:research.swtch.com/openssl 静态数组的元素具有静态存储持续时间,因此被零填充。在数组或其他聚合中没有区别。
  • @BenVoigtq 我明白了,非常感谢!
【解决方案2】:

这取决于您忘记提及的可能因素。

如果您的Test 没有用户定义的构造函数,或者您的用户定义的构造函数没有初始化数组,并且您将Test 类型的对象声明为

Test test; // no initializer supplied

那么它将以与您上面描述的完全相同的方式运行。对于自动(本地)对象,数组的内容将保持不可预测。对于静态对象,内容保证为零。

如果你的类有一个用户定义的构造函数,那么这一切都取决于构造函数的作用。同样,请记住,在任何构造函数有机会做任何事情之前,静态对象总是初始化为零。

如果您的类是一个聚合,那么内容可能取决于您在对象声明中提供的聚合初始化器。例如

Test test = {};

即使对于自动(本地)对象,也会对数组进行零初始化。

【讨论】:

  • 如果在构造函数初始化列表中调用testArray(),数组中的每个元素都将被初始化值(这意味着在这种特殊情况下设置为0)
  • 这些情况都不是默认初始化。问题询问默认初始化期间会发生什么。
  • @Ben Voigt:这个问题显然滥用了“默认初始化”一词。当人们认为如果他们什么都不做就会发生某种“默认初始化”时,这种情况经常发生。实际上,C++ 中的“默认初始化”意味着不同的东西。这就是为什么我不将答案限制为“默认初始化”。
【解决方案3】:

我相信,如果你在声明的时候不初始化它,它可以被设置为任何东西。有时它是一个地址或随机值。

最佳做法是在声明后进行初始化。

【讨论】:

    猜你喜欢
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 2016-03-27
    • 2019-09-10
    • 2012-08-29
    • 1970-01-01
    • 1970-01-01
    • 2021-06-13
    相关资源
    最近更新 更多