为什么不能在C ++中的非POD结构上使用offsetof? [英] Why can't you use offsetof on non-POD structures in C++?

查看:329
本文介绍了为什么不能在C ++中的非POD结构上使用offsetof?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究如何获得一个成员的内存偏移到C ++中的类,并在维基百科中遇到这个问题:

I was researching how to get the memory offset of a member to a class in C++ and came across this on wikipedia:


在C ++代码中,不能使用offsetof访问不是普通数据结构的结构或类的成员。

In C++ code, you can not use offsetof to access members of structures or classes that are not Plain Old Data Structures.

我试过了,它似乎工作正常。

I tried it out and it seems to work fine.

class Foo
{
private:
    int z;
    int func() {cout << "this is just filler" << endl; return 0;}

public: 
    int x;
    int y;
    Foo* f;

    bool returnTrue() { return false; }
};

int main()
{
    cout << offsetof(Foo, x)  << " " << offsetof(Foo, y) << " " << offsetof(Foo, f);
    return 0;
}



我有几个警告,但它编译,运行时它给出合理的输出:

I got a few warnings, but it compiled and when run it gave reasonable output:

Laptop:test alex$ ./test
4 8 12

我想我或者误解了POD数据结构是什么,或者我错过了一些其他的谜题。我看不出什么问题。

I think I'm either misunderstanding what a POD data structure is or I'm missing some other piece of the puzzle. I don't see what the problem is.

推荐答案

简短的答案:offsetof是一个只有C ++标准的功能,因此,它基本上限于在C中可以做的东西。C ++只支持它必须为C兼容性。

Short answer: offsetof is a feature that is only in the C++ standard for legacy C compatibility. Therefore it is basically restricted to the stuff than can be done in C. C++ supports only what it must for C compatibility.

由于offsetof基本上是一个黑客)依赖于简单的内存模型支持C,它将需要很多的自由,从C ++编译器实现者如何组织类实例布局。

As offsetof is basically a hack (implemented as macro) that relies on the simple memory-model supporting C, it would take a lot of freedom away from C++ compiler implementors how to organize class instance layout.

效果是, offsetof通常会在C ++中工作(取决于源代码和编译器),即使在没有标准支持的地方,除非它没有。所以你应该非常小心在C ++中使用offsetof,特别是因为我不知道一个编译器会生成一个警告非POD使用...

The effect is that offsetof will often work (depending on source code and compiler used) in C++ even where not backed by the standard - except where it doesn't. So you should be very careful with offsetof usage in C++, especially since I do not know a single compiler that will generate a warning for non-POD use...

< b>编辑:如您要求的示例,以下可能会澄清问题:

Edit: As you asked for example, the following might clarify the problem:

#include <iostream>
using namespace std;

struct A { int a; };
struct B : public virtual A   { int b; };
struct C : public virtual A   { int c; };
struct D : public B, public C { int d; };

#define offset_d(i,f)    (long(&(i)->f) - long(i))
#define offset_s(t,f)    offset_d((t*)1000, f)

#define dyn(inst,field) {\
    cout << "Dynamic offset of " #field " in " #inst ": "; \
    cout << offset_d(&i##inst, field) << endl; }

#define stat(type,field) {\
    cout << "Static offset of " #field " in " #type ": "; \
    cout.flush(); \
    cout << offset_s(type, field) << endl; }

int main() {
    A iA; B iB; C iC; D iD;
    dyn(A, a); dyn(B, a); dyn(C, a); dyn(D, a);
    stat(A, a); stat(B, a); stat(C, a); stat(D, a);
    return 0;
}

当尝试定位 内部类型 B 静态,而当实例可用时它工作。这是因为虚拟继承,其中基类的位置存储在查找表中。

This will crash when trying to locate the field a inside type B statically, while it works when an instance is available. This is because of the virtual inheritance, where the location of the base class is stored into a lookup table.

虽然这是一个假设的例子,一个实现可以使用查找表也​​找到类实例的public,protected和private部分。或者使查找完全动态(使用字段的哈希表)等。

While this is a contrived example, an implementation could use a lookup table also to find the public, protected and private sections of a class instance. Or make the lookup completely dynamic (use a hash table for fields), etc.

标准通过将offsetof限制为POD使用POD结构体的散列表...:)

The standard just leaves all possibilities open by restricting offsetof to POD (IOW: no way to use a hash table for POD structs... :)

另一个注意事项:对于这个例子,我不得不重新实现offsetof(这里:offset_s)我为虚拟基类的字段调用offsetof。

Just another note: I had to reimplement offsetof (here: offset_s) for this example as GCC actually errors out when I call offsetof for a field of a virtual base class.

这篇关于为什么不能在C ++中的非POD结构上使用offsetof?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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