hhafez
hhafez

Reputation: 39750

Structure of a C++ Object in Memory Vs a Struct

If I have a class as follows

   class Example_Class 
   {
       private:
         int x; 
         int y; 
       public: 
         Example_Class() 
         { 
             x = 8;
             y = 9;
         }
       ~Example_Class() 
       { } 
   };

And a struct as follows

struct
{
   int x;
   int y;
} example_struct;

Is the structure in memory of the example_struct simmilar to that in Example_Class

for example if I do the following

struct example_struct foo_struct;
Example_Class foo_class = Example_Class();

memcpy(&foo_struct, &foo_class, sizeof(foo_struct));

will foo_struct.x = 8 and foo_struct.y = 9 (ie: the same values as the x,y values in the foo_class) ?

The reason I ask is I have a C++ library (don't want to change it) that is sharing an object with C code and I want to use a struct to represent the object coming from the C++ library. I'm only interested in the attributes of the object.

I know the ideal situation would be to have Example_class wrap arround a common structure between the C and C++ code but it is not going to be easy to change the C++ library in use.

Upvotes: 60

Views: 41234

Answers (8)

j_random_hacker
j_random_hacker

Reputation: 51226

The C++ standard guarantees that memory layouts of a C struct and a C++ class (or struct -- same thing) will be identical, provided that the C++ class/struct fits the criteria of being POD ("Plain Old Data"). So what does POD mean?

A class or struct is POD if:

  • All data members are public and themselves POD or fundamental types (but not reference or pointer-to-member types), or arrays of such
  • It has no user-defined constructors, assignment operators or destructors
  • It has no virtual functions
  • It has no base classes

About the only "C++-isms" allowed are non-virtual member functions, static members and member functions.

Since your class has both a constructor and a destructor, it is formally speaking not of POD type, so the guarantee does not hold. (Although, as others have mentioned, in practice the two layouts are likely to be identical on any compiler that you try, so long as there are no virtual functions).

See section [26.7] of the C++ FAQ Lite for more details.

Upvotes: 77

Zoran Horvat
Zoran Horvat

Reputation: 11301

In the early days of C++ compilers there were examples when compiler first changes struct keywords with class and then compiles. So much about similarities.

Differences come from class inheritance and, especially, virtual functions. If class contains virtual functions, then it must have a pointer to type descriptor at the beginning of its layout. Also, if class B inherits from class A, then class A's layout comes first, followed by class B's own layout.

So the precise answer to your question about just casting a class instance to a structure instance is: depends on class contents. For particular class which has methods (constructor and non-virtual destructor), the layout is probably going to be the same. Should the destructor be declared virtual, the layout would definitely become different between structure and class.

Here is an article which shows that there is not much needed to do to step from C structures to C++ classes: Lesson 1 - From Structure to Class

And here is the article which explains how virtual functions table is introduced to classes that have virtual functions: Lesson 4 - Polymorphism

Upvotes: 2

Dominik Grabiec
Dominik Grabiec

Reputation: 10655

You probably just derive the class from the struct, either publicly or privately. Then casting it would resolve correctly in the C++ code.

Upvotes: -2

Chuck
Chuck

Reputation: 237010

Why not explicitly assign the class's members to the struct's when you want to pass the data to C? That way you know your code will work anywhere.

Upvotes: 0

Mike Thompson
Mike Thompson

Reputation: 6738

Classes & structs in C++ are the equivalent, except that all members of a struct are public by default (class members are private by default). This ensures that compiling legacy C code in a C++ compiler will work as expected.

There is nothing stopping you from using all the fancy C++ features in a struct:

struct ReallyAClass
{
    ReallyAClass();
    virtual !ReallAClass();

    /// etc etc etc
};

Upvotes: 0

Nick
Nick

Reputation: 6846

To add to what other people have said (eg: compiler-specific, will likely work as long as you don't have virtual functions):

I would highly suggest a static assert (compile-time check) that the sizeof(Example_class) == sizeof(example_struct) if you are doing this. See BOOST_STATIC_ASSERT, or the equivalent compiler-specific or custom construction. This is a good first-line of defense if someone (or something, such as a compiler change) modifies the class to invalidate the match. If you want extra checking, you can also runtime check that the offsets to the members are the same, which (together with the static size assert) will guarantee correctness.

Upvotes: 3

Greg Hewgill
Greg Hewgill

Reputation: 992737

In the case you describe, the answer is "probably yes". However, if the class has any virtual functions (including virtual destructor, which could be inherited from a base class), or uses multiple inheritance then the class layout may be different.

Upvotes: 7

ChrisW
ChrisW

Reputation: 56083

Is the structure in memory of the example_struct simmilar to that in Example_Class

The behaviour isn't guaranteed, and is compiler-dependent.

Having said that, the answer is "yes, on my machine", provided that the Example_Class contains no virtual method (and doesn't inherit from a base class).

Upvotes: 10

Related Questions