假设我有一个与此类似的对象:
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,
},
...
答案 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
是什么)。