默认情况下,C ++结构的成员是否初始化为0?


Answers:


263

如果不初始化结构,则它们不为null。

Snapshot s; // receives no initialization
Snapshot s = {}; // value initializes all members

第二个将使所有成员为零,第一个将其保留为未指定的值。请注意,它是递归的:

struct Parent { Snapshot s; };
Parent p; // receives no initialization
Parent p = {}; // value initializes all members

第二个将p.s.{x,y}为零。如果您的结构中有构造函数,则不能使用这些聚合初始化程序列表。如果是这种情况,则必须向这些构造函数添加适当的初始化

struct Snapshot {
    int x;
    double y;
    Snapshot():x(0),y(0) { }
    // other ctors / functions...
};

x(), y()会将x和y都初始化为0。请注意,您可以不考虑其类型而将它们初始化:然后进行值初始化,通常会产生适当的初始值(对于int为0,对于double为0.0,为用户定义的调用默认构造函数)具有用户声明的构造函数的类型,...)。这很重要,特别是如果您的结构是模板。


1
这在我的编译器中产生了很多警告。
克莱尔·威廉姆森

1
Roger:尝试在初始化器中使用命名的结构,这就是我所做的,并且在VC 2012中我没有收到任何警告:Snapshot s = Snapshot();
Kit10 2013年

@Johannes Schaub-litb是否Snapshot s = {};适用于非POD成员(将他们归零)?
ontherocks 2013年

2
现在,C ++ 11允许您在结构或类的定义中对其进行初始化,如下所示:struct Snapshot {double x {0}; //大括号int y = 0; //或者只是老式的“通过分配”风格,实际上也是初始化};
ikku100 '16

1
是“快照s = {};” 标准的一部分?
斯特凡

40

不,默认情况下它们不是0。确保所有值或默认为0的最简单方法是定义构造函数

Snapshot() : x(0), y(0) {
}

这样可以确保所有对Snapshot的使用都具有初始化值。


24
缺点是该结构不再是POD类型,因为它具有构造函数。这将破坏某些操作,例如将其写入临时文件。
finnw

16
@finnw:C ++ 11修复了此问题,尽管该结构不是POD,但它是“标准布局”。
Ben Voigt 2012年

19

一般来说,没有。但是,在函数/ will /中声明为file-scope或static的结构将初始化为0(就像这些作用域的所有其他变量一样):

int x; // 0
int y = 42; // 42
struct { int a, b; } foo; // 0, 0

void foo() {
  struct { int a, b; } bar; // undefined
  static struct { int c, d; } quux; // 0, 0
}

1
这确实不是一个安全的假设。您不应该依赖于未初始化的任何事物的值
Hasturkun

24
静态存储持续时间对象始终初始化为零- 有关标准的引用,请参见stackoverflow.com/questions/60653/…。这是否是好的风格是另一回事。
bdonlan

12

使用POD,您还可以编写

Snapshot s = {};

您不应该在C ++中使用memset,memset的缺点是,如果结构中存在非POD,它将破坏它。

或像这样:

struct init
{
  template <typename T>
  operator T * ()
  {
    return new T();
  }
};

Snapshot* s = init();

@LightnessRacesinOrbit哦,w?
本·辛克莱

@Andy大多数Vexing解析器将看起来像普通ctor的东西SomeType foo();(虽然可能与其他ctor一起发生)转换为函数定义(在这种情况下,foo返回的函数SomeType)。对不起,坏死,但是如果有人偶然发现,我想回答。
基金莫妮卡的诉讼

7

在C ++中,使用无参数构造函数。在C中,您没有构造函数,因此请使用memset-或有趣的解决方案-指定的初始化程序:

struct Snapshot s = { .x = 0.0, .y = 0.0 };

我相信这是C,而不是C ++。在某些C ++编译器下将无法编译。我在Cygwin或MinGW下遇到编译失败。
2015年

3

我相信正确的答案是它们的值是不确定的。通常,在运行代码的调试版本时,它们会初始化为0。运行发行版时通常不是这种情况。


2
实际上,调试版本恰好已经存在0于内存中的那些位置。这与初始化不同!
Lightness Races in Orbit 2012年

3

由于这是一个POD(本质上是C结构),因此用C方式初始化它几乎没有什么害处:

Snapshot s;
memset(&s, 0, sizeof (s));

或类似

Snapshot *sp = new Snapshot;
memset(sp, 0, sizeof (*sp));

不过,我不会calloc()在C ++程序中使用。


3
同样适用于双倍;全零位不一定是0.0。但是,您可以检查是否具有IEEE754双精度,在这种情况下它必须可以工作。
MSalters

1

将pod成员移至基类以缩短初始化程序列表:

struct foo_pod
{
    int x;
    int y;
    int z;
};

struct foo : foo_pod
{
    std::string name;
    foo(std::string name)
        : foo_pod()
        , name(name)
    {
    }
};

int main()
{
    foo f("bar");
    printf("%d %d %d %s\n", f.x, f.y, f.z, f.name.c_str());
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.