大括号括起来的初始化列表

时间:2010-12-27 15:08:12

标签: c++ initialization

假设我有一个与此类似的对象:

struct MenuDef
{
    int titleResourceId;

    struct MenuItemDef {
        char*               name;
        int                 value;
        SomeFunctionPtr     someFactory;
    } menuItems[10];
};

这是初始化的:

const MenuDef m = {
    1,
    {
        {
            "zero",
            0,
            (SomeFunctionPtr) & MenuButton::factory,
        },
        {
            "one",
            1,
            (SomeFunctionPtr) & MenuButton::factory,
        },
        {
            "two",
            2,
            (SomeFunctionPtr) & MenuButton::factory,
        },
    }
};

可以安全地假设 m.menuItems[3].someFactory == 0

例如在这样的循环中:

for ( int i = 0; m.menuItems[i].someFactory != 0; ++i)

还是必须插入最后一个元素来手动标记数组才安全?

...
        {
            "two",
            2,
            (SomeFunctionPtr) & MenuButton::factory,
        },
        {
            "",
            0,
            (SomeFunctionPtr) 0,
        },
...

2 个答案:

答案 0 :(得分:4)

根据8.5.1 / 7,我认为它是安全的:

  

如果初始化程序较少   列表中的成员比   聚合,然后每个成员不   明确初始化应为   价值初始化(8.5)。

提醒一下:

  

对值类型的对象进行值初始化   T表示:

     
      
  • 如果T是具有用户声明的构造函数(12.1)的类类型(第9节),   那么T的默认构造函数是   调用(初始化为   如果T无法进入,则形成不良   默认构造函数);
  •   
  • 如果T是没有用户声明的构造函数的非联合类类型,   那么每个非静态数据成员和   T的基类组件是   值初始化;
  •   
  • 如果T是数组类型,则每个元素都是值初始化的;
  •   
  • 否则,该对象为零初始化
  •   

答案 1 :(得分:2)

您的问题的答案取决于语言版本(C ++ 98或C ++ 03),在C ++ 98中,您可能无法提供某些细节。即,SomeFuncPtr是什么?这是普通的函数指针还是成员函数指针?

如果这是一个成员函数指针,那么在C ++ 98版本的语言规范中,内部类不是POD。由于它是非POD类,因此通过调用其默认构造函数来对其余的数组成员进行默认初始化。内部类的编译器提供的默认构造函数不执行任何操作,因此数组的其余成员将包含垃圾。

在C ++ 03版本的语言规范中,剩余的数组成员是值初始化的,无论SomeFuncPtr是什么,它都会对数组的其余部分进行零初始化。

因此,如果您使用符合C ++ 03的编译器,那么您没问题。如果您关心可以向后移植到C ++ 98编译器,那么您可能希望包含该显式终止初始化程序(同样取决于SomeFuncPtr是什么)。