保证它们按照声明的顺序以递增的地址出现。对于没有干预访问说明符的数据成员而言,这通常是正确的,因此如果类中有其他数据成员,那么它们可以干预的唯一方法就是那里有访问说明符。
我认为修改填充字节不能保证安全。我认为不能保证实现不会在数据成员之间放置“重要的东西”,尽管我不能立即想到实现想要放在那里的任何东西。为设计奇特的精确标记 GC 输入信息?用于测试缓冲区溢出的可识别值?
不能保证所有位为零表示空函数指针。
您可以使用以下方法处理全位零表示的问题:
std::fill(&func1, &func4 + 1, (void(*)(void))0);
但这仍然会留下填充问题。保证数组中没有填充,但(按照标准)在类中没有。您的实现使用的 ABI 可能会在必要的程度上指定结构布局,以确保上述类的布局与 4 个函数指针的数组相同。
另一种方法是执行以下操作:
struct function_pointers {
void (*func1)();
void (*func2)();
void (*func3)();
void (*func4)();
};
class C : private function_pointers
{
public:
C() : function_pointers() {}
};
初始化程序function_pointers()
规定(因为它没有用户声明的构造函数)的成员function_pointers
是零初始化的,即使C
它本身的实例只是默认初始化的。function_pointers
可以是数据成员而不是基类,如果您更喜欢输入更多内容来访问func1
等。
请注意,C
现在在 C++03 中是非 POD。在 C++11C
中,在此更改之后仍然是标准布局,但如果在 中定义了任何数据成员,则不会是标准布局C
,并且它不是一个平凡的类。因此,如果您依赖 POD/标准/琐碎性,请不要这样做。而是保留C
原样的定义并使用聚合初始化 ( C c = {0};
) 将 C 的实例初始化为零。