First member of class of C++ object
Asked Answered
S

3

1

I know the following is bad but I was under the impression that the first member of class is the starting address of the class. Is it wrong ?

   class A{
      public:
       int a;
       int b;
   };
  
   class B{
     public :
       int x;
   };

   int main()
   {
        B *pb=new B();
        A *pa=(A*)pb;
        pa->a++;
   }

I was under the impression that pb->x would be incremented by 1. Is it always true or undefined ? Why does it change when we have user defined constructors or virtual functions ?

Swarth answered 19/8, 2014 at 7:30 Comment(2)
Yes. It is bad! So bad that the answer should be irrelevant.Magnanimity
Your question doesn't matter! All what you can do with this is bad design and mostly undefined behaviour. Simple answer: Never do that! It maybe works today but is not defined that it will work tomorrow or with any other compiler.Edna
L
4

This holds only true if your class is of standard_layout type. This you can test using the type trait is_standard_layout

 std::cout << std::is_standard_layout<A>::value << '\n';
 std::cout << std::is_standard_layout<B>::value << '\n';

For other classes, you have additional information stored in memory, which is compiler specific and not standardized. You can have a look at This question where some memory layouts are discussed and showed.

For your second example/question the standard has the following quote (5.2.10/7, N3337 draft):

An object pointer can be explicitly converted to an object pointer of a different type. When a prvalue v of type “pointer to T1” is converted to the type “pointer to cv T2”, the result is static_cast<cv T2*>(static_cast<cv void*>(v)) if both T1 and T2 are standard-layout types (3.9) and the alignment requirements of T2 are no stricter than those of T1, or if either type is void. Converting a prvalue of type “pointer to T1” to the type “pointer to T2” (where T1 and T2 are object types and where the alignment requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer value. The result of any other such pointer conversion is unspecified.

If I read and interpret this correctly, then your example is unspecified, as the alignment requirements of A are bigger that those of B. However, the other way should be ok, e.g:

int main()
{
    A *pa=new A();
    B *pb=reinterpret_cast<B*>(pa);
    pb->x++;
    std::cout << pa->a;
}
Lindholm answered 19/8, 2014 at 7:36 Comment(4)
You can cast a pointer to an object of a standard layout type to a pointer to its first member, but I'm not completely sure about this one. Can you add a supporting quote from The Standard?Allo
Most of those rules are fairly intuitive, but rules #3 and #6 seem ridiculous to me, and I can't even understand what #5 is trying to say.Sprinkling
@ValekHalfHeart #3 is to allow compilers to reorder class members based on access. #6 needs to be read in conjunction with #5; if the class has a non-static data member then all its base classes must be empty (per #5), but if the first non-static data member is of the same type as a base class then the compiler must give it and the (empty) base-class subobject distinct addresses because they are distinct objects.Blueness
@Allo I added the section of the standard which describes this. I can't say if I interpreted it correctly, but as it seems, casting from A to B should be fine, while casting from B to A is unspecified.Lindholm
L
2

You've violated strict aliasing by casting the pointer to another class. You can only cast it to the type of the first member, if your class is standard-layout.

Lammas answered 19/8, 2014 at 7:38 Comment(0)
W
-2

Yes you are absolutely wrong, you can never take anything like that for granted, those are compiler specific contracts that C++ does not guarantee.

I believe you confused classes with C++ arrays: For example the pointer to the first member of a char array is the same as the pointer to that array.

Wahhabi answered 19/8, 2014 at 7:35 Comment(7)
Any supporting link to specifications?Atlee
I don't quite understand why this answer is downvotedWahhabi
Because it's incorrect. Standard-layout does in fact absolutely make this guarantee and even the original C spec did it.Lammas
what if the first member is a virtual function in a hierarchy ? what if the class is itself part of a hierarchy ? I think either you are not certain about what you're talking about (with respect) or you are not considering all the possibilities...Wahhabi
We didn't see any virtual methods in the code shown though.Atlee
@jaffar exaclty this is what standard-layout guarantees. If your class has any of those 'obstacles', it is not Standard-layout. On the other hand, if your class is standard-layout, it is well defined.Lindholm
@Lindholm yes you're correct, the original question though makes no attempt at any clarification so I thought 'no' was the safer answer given the "obstacles" that could be presentWahhabi

© 2022 - 2024 — McMap. All rights reserved.