C++ 括号内初始值设定项列表

C++ 括号内初始值设定项列表,c++,initialization,C++,Initialization,假设我有一个类似于此的对象: struct MenuDef { int titleResourceId; struct MenuItemDef { char* name; int value; SomeFunctionPtr someFactory; } menuItems[10]; }; 初始化如下: const MenuDef m = { 1

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

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,
        },
    }
};
for ( int i = 0; m.menuItems[i].someFactory != 0; ++i)
假设m.menuItems[3].someFactory==0是否安全

例如,在这样的循环中:

const MenuDef m = {
    1,
    {
        {
            "zero",
            0,
            (SomeFunctionPtr) & MenuButton::factory,
        },
        {
            "one",
            1,
            (SomeFunctionPtr) & MenuButton::factory,
        },
        {
            "two",
            2,
            (SomeFunctionPtr) & MenuButton::factory,
        },
    }
};
for ( int i = 0; m.menuItems[i].someFactory != 0; ++i)
或者为了安全起见,我必须插入最后一个元素来手动标记数组的结尾吗


根据8.5.1/7,我相信它是安全的:

如果列表中的初始值设定项较少 列表中没有成员 聚合,则每个成员不 显式初始化应为 值初始化为8.5

提醒大家:

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

如果T是类类型子句9,用户声明构造函数为12.1, 那么T的默认构造函数是 调用,初始化为 如果T没有可访问的 默认构造函数; 如果T是没有用户声明构造函数的非联合类类型, 然后,每个非静态数据成员和 T的基类组件是 值初始化; 如果T是数组类型,则每个元素都初始化为值; 否则,对象初始化为零
根据8.5.1/7,我相信它是安全的:

如果列表中的初始值设定项较少 列表中没有成员 聚合,则每个成员不 显式初始化应为 值初始化为8.5

提醒大家:

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

如果T是类类型子句9,用户声明构造函数为12.1, 那么T的默认构造函数是 调用,初始化为 如果T没有可访问的 默认构造函数; 如果T是没有用户声明构造函数的非联合类类型, 然后,每个非静态数据成员和 T的基类组件是 值初始化; 如果T是数组类型,则每个元素都初始化为值; 否则,对象初始化为零
您的问题的答案取决于语言版本C++98或C++03,在C++98中,取决于您未能提供的一些详细信息。也就是说,什么是SomeFuncPtr?这是普通函数指针还是成员函数指针

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

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


因此,如果您使用的是与C++03兼容的编译器,那么就可以了。如果您想向后移植到C++98编译器,您可能希望包含显式终止初始值设定项,这同样取决于SomeFuncPtr是什么。

您的问题的答案取决于语言版本C++98或C++03,在C++98中,取决于您未能提供的某些详细信息。也就是说,什么是SomeFuncPtr?这是普通函数指针还是成员函数指针

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

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


因此,如果您使用的是与C++03兼容的编译器,那么就可以了。如果您想向后移植到C++98编译器,您可能希望包含显式终止初始值设定项,这同样取决于SomeFuncPtr是什么。

是否不需要默认构造函数将值初始化为0?我还建议不要依赖于此,而是存储大小以使其更具可读性,甚至更改为向量。@marcog:用值初始化的定义更新了我的答案。根据这句话,我相信你不需要用户声明的构造函数。结构不是一种类类型吗?@Marco:这里我们有一个非联合类类型,没有用户声明的构造函数bullet 2+1,接受。这正是我想要的,谢谢是否不需要默认构造函数将值初始化为0?我还建议不要依赖于此,而是存储大小以使其更具可读性,甚至更改为向量。@marcog:用值初始化的定义更新了我的答案。根据这句话,我相信你不需要用户声明的构造函数。结构不是一种类类型吗?@marcog:这里我们有一个非联合类类型,没有用户声明的构造函数bullet 2+1,接受
艾德。那正是我想要的,谢谢这并不能回答您的问题,我认为@ICECRORIM做得对,但您必须在初始化中强制转换函数地址这一事实应该是一个巨大的危险信号。即使它现在似乎可以工作,但将来编译器中可能会发生一些变化,并且由于在不兼容的函数指针类型之间进行强制转换,它将无法工作。@Mark B不确定您的意思。。。你能提供一个例子吗?这并不能回答你的问题,我认为@ICEChrime是对的,但你必须在初始化中转换函数地址这一事实应该是一个很大的危险信号。即使它现在似乎可以工作,但将来编译器中可能会发生一些变化,并且由于在不兼容的函数指针类型之间进行强制转换,它将无法工作。@Mark B不确定您的意思。。。你能举个例子吗?好的。我让人们不想要C++0x答案。但是,来吧,你不必处理C++98.+1。实际上,它是一个静态成员函数,与普通函数指针几乎相同。但感谢您的澄清,因为我不确定是否有符合C++03的编译器可用于我必须部署的所有平台:好啊我让人们不想要C++0x答案。但是,来吧,你不必处理C++98.+1。实际上,它是一个静态成员函数,与普通函数指针几乎相同。但感谢您的澄清,因为我不确定是否有符合C++03的编译器可用于我必须部署的所有平台: