Given a variable foo
of type FooClass*
and a member variable in that class named bar
, is the distance between foo
and &(foo->bar)
the same in any situation with some constraints:
FooClass
is a non-POD type.
We know that foo
will always point to an instance of FooClass
, and not some subtype of it.
We only care about behaviour under a single compiler and a single compilation; that is, the value this may result in under gcc is never used in code compiled with MSVC, and it is never saved to be re-used between compilations. It is computed in the binary and used in the binary, and that is it.
We don't use a custom new
, although some instances of the class may be stack-allocated and some heap-allocated.
There is no explicit ctor
for FooClass
; it relies upon the compiler-generated one (and each of the fields in FooClass
is either POD or default-constructable).
I can't find a guarantee either way on this in the standard (nor did I expect to), but my rudimentary testing with gcc leads me to believe that it will always be the case there. I also know that this guarantee is made for POD-types, but let us assume this type can't be POD.
An update/clarification: this is just for a single compilation of a single binary; the calculated offsets will never leave that single execution. Basically, I want to be able to uniquely identify the fields of a class in a static map and then be able to lookup into that map for some macro/template/EVIL trickery. It is merely for my own amusement, and no life support machines will rely on this code.
After you have compiled your program, Yes*.
The offset will remain constant.
There is one very important restriction, however: foo must be pointing specifically to a FooClass object. Not a class derived from FooClass, or anything else for that matter.
The reason that C++ makes the POD distinction regarding member offsets is because both multiple inheritance and the location (or lack of) a vtable pointer can create situations where the address of an object is not the same as the address of that object's base.
Under a single compiler where the compiler settings are always the same and there is nothing added to or taken away from FooClass, then yes, the distance between the address stored at foo
and &(foo->bar)
will always be the same, or the compiler wouldn't be able to generate proper code that worked across compilation units.
However, once you add anything to the class, or change the compiler settings, all bets are off.
As far as I know, this should always be the case, POD class or not. At compile time, based on the compiler, architecture, settings, etc., the compiler determines the size of the class and the offsets of all its members. This is then fixed for all instances of the class in the compilation unit (and by extension the linked unit, if the one-definition rule is preserved).
Since the compiler treats type pointers literally, even if the underlying type is wrong (eg: the pointer has been c-style cast incorrectly), the computed distance between &foo and &(foo.bar) will be the same, since the offset is known statically at compile time.
Note: This has definitely been done before, effectively. See, for example, Microsoft's ATL data binding code using their 'offsetof' macro...
I'm no expert but i gonna try answering you anyway :)
private
, public
or protected
. Within such a section, the order is that of the definition of the members, but across those sections, order is arbitrary and unspecified. So after all i don't think you have any guarantee that the offset will be constant across compilations. For considerations within one compilation (so if we would play with a compiler whose generated code uses an ABI that changes with each different compilation), the offset just can't be different. But even if you know the offset, you can't access the member. Your only way to access a member is using the member access operator ->
and .
(that's said in 9.2/9).
Why not use data member pointers? They allow accessing members safely. Here is an example: (looking up members by name).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With