是否保证班级成员在内存中是连续的? [英] Are class members guaranteed to be contiguous in memory?

查看:49
本文介绍了是否保证班级成员在内存中是连续的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类,其中包含许多函数指针,并且我希望在构造对象时将它们全部初始化为NULL.为此,我计划在从第一个指针到最后一个指针的内存位置上使用memset,但是,我不确定这是否会在100%的时间内起作用.

I have a class which holds a number of function pointers and I would like for them all to be initialized to NULL when objects are constructed. To do this I was planning on using memset on the memory locations from the first pointer to that of the last pointer however, I am unsure if this would work 100% of the time.

是否可以保证,如果在类中连续声明这些函数指针,则它们的存储位置也将是连续的.我认为填充不会影响我要执行的操作,因为任何填充字节也会被设置为NULL.

Is it guaranteed that if these function pointers are declared contiguously within the class that their memory locations would also be contiguous. I assume that padding won't affect what I'm trying to do as any padding bytes would just be set to NULL also.

示例类实现

class C
{
private:
    void (*func1)();
    void (*func2)();
    void (*func3)();
    void (*func4)();
};

推荐答案

可以确保它们以声明的顺序以递增的地址出现.通常对于不介入访问说明符的数据成员而言,这是正确的,因此,如果类中还有其他数据成员,则它们可以进行干预的唯一方法就是其中存在访问说明符.

It is guaranteed that they appear with increasing addresses in the order declared. This is true in general of data members without intervening access specifiers, so if there are other data members in the class then the only way they could intervene is if there are access specifiers in there.

我认为修改填充字节不保证是安全的.我不保证该实现不会在数据成员之间放置重要的东西",尽管我无法立即想到实现会想要 放入其中的任何内容.设计奇怪的精确标记GC的类型信息?可识别的值以测试缓冲区超限吗?

I don't think it's guaranteed to be safe to modify padding bytes. I don't think it's guaranteed that the implementation won't put "something important" in between data members, although I can't immediately think of anything an implementation would want to put in there. Type information for a strangely-designed accurate-marking GC? Recognizable values to test for buffer overruns?

不能保证全零位表示空函数指针.

It's not guaranteed that all-bits-zero represents a null function pointer.

您可以使用以下方法处理全零位表示形式的问题:

You could deal with the issue of the all-bits-zero representation using something like:

std::fill(&func1, &func4 + 1, (void(*)(void))0);

但是这仍然会留下填充的问题.您可以确保在数组中没有填充,但不能(按标准)在类中.您的实现所使用的ABI可能会以必要的程度指定结构布局,以确保上述类与4个函数指针的数组相同.

but that would still leave the issue of padding. You're guaranteed no padding in an array, but not (by the standard) in a class. The ABI used by your implementation might specify struct layout to the degree necessary to ensure that your class above is laid out the same as an array of 4 function pointers.

另一种方法是执行以下操作:

An alternative is to do the following:

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 本身仅是默认初始化的.如果您想输入更多内容来访问 func1 等,则 function_pointers 可以是数据成员而不是基类.

The initializer function_pointers() dictates that (since it doesn't have a user-declared constructor) the members of function_pointers are zero-initialized even if the instance of C itself is only default-initialized. function_pointers could be a data member rather than a base class, if you prefer to type a bit more to access func1 etc.

请注意,在C ++ 03中, C 现在不是POD.在C ++ 11中, C 保留此更改后的标准布局,但如果 C 中定义了任何数据成员,则不会成为标准布局,并且不是琐碎的类.因此,如果您依赖POD/标准/琐碎性,则不要这样做.取而代之的是保留 C 的定义,并使用聚合初始化( C c = {0}; )对C的实例进行零初始化.

Note that C is now non-POD in C++03. In C++11 C remains standard-layout after this change, but would not be standard-layout if there were any data members defined in C, and it is not a trivial class. So if you were relying on POD/standard/trivial-ness then don't do this. Instead leave the definition of C as it is and use aggregate initialization (C c = {0};) to zero-initialize instances of C.

这篇关于是否保证班级成员在内存中是连续的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆