MEMORY LAYOUT OF C++ OBJECT, virtual function works internally
Reading Time: 4 minutes

This article is the collection of concept I have acquired while introducing myself to C++ by googling here & there. This material is also not in order. I have just collected the answer to my quick question. And write it down here. But one thing I can assure you is that once you go through this article. You can connect many broken thought of understanding on what runs “Inside the C++ object model”. And why people call it as it runs C internally.

Note: In addition, here I have not considered name mangling & other compiler attributes for simplicity. Also not shown how object memory layout created. So, I have discussed it here. Code augmentation depends on compiler implementation, there is no such standard define.

Default Member-Functions Created by the Compiler Inside the C++ Object Model

Suppose you have declared class like:

 class Thing {}; 
  • The compiler will probably synthesize this class as:
class Thing {
    Thing();                        // default constructor
    Thing(const Thing&);            // copy c'tor
    Thing& operator=(const Thing&); // copy-assign
    ~Thing();                       // d'tor
    // C++11:
    Thing(Thing&&);                 // move c'tor
    Thing& operator=(Thing&&);      // move-assign
  • So by default compiler will generate:
    1. default constructor
    2. copy constructor
    3. copy-assign operator
    4. destructor
    5. move constructor
    6. move-assign operator

Note: This stands true till C++ 14.

  • The compiler creates all default/implicitly-declared member-functions when it needed. A compiler cannot create default member-functions when it’s no use.

How C++ Object Model Used in Function?

X foobar()
    X xx;
    X *px = new X;

    // foo() is virtual function;

    delete px;
    return xx;
  • The probable compiler transformation would be:
void foobar(X &result) {
	X::X(&result);		  // Constructor call, NRVO
	px = _new(sizeof(X)); // expand X *px = new X;
	if (px != 0)

	foo(&result);		 // replaced xx with result
	(*px->_vtbl[2])(px); // px->foo(): using dynamic dispatch

	// Expand delete px;
	if (px != 0) {
		(*px->_vtbl[1])(px); // Virtual destructor
	// replace named return statement
	// no need to destroy local object xx

How Class/Object-Oriented Code Transformed Into Sequential Code?

  • Let’s take the following example to understand it:
struct foo
    int m_var;

    void print()
        cout << m_var << endl;
  • The compiler treats this as :
struct foo
    int m_var;

void foo::print(foo *this)
  • As you can see above, objects & methods are a separate entity. An object only represents data members.
  • Therefore, all the methods in class/struct contain implicit this pointer as the first argument using which all non-static data members are accessed.
  • Static data members are not part of class/struct. Because it usually resides in a data segment of memory layout. So it accesses directly(or using segment registers).
  • So this is the reason if you print the size of the above class. Hence, It prints 4 because all methods are a separate entity which operates on the object by using implicit this pointer.

How & Where Constructor Code Transform/Synthesize With Inheritance & Composition Class?

class Foo 

class base 

class Bar /* : public base */
  Foo foo; 
  char *str; 
    str = 0;
  • Compiler augmented Bar constructor would look like:
  foo.Foo::Foo(); // augmented compiler code
  cout<<"Bar"<<endl; // explicit user code
  str = 0; // explicit user code
  • Similarly, multiple class member objects require a constructor initialization. The language specifies that the constructors would be invoked in the order of member declaration within the class. This is accomplished by the compiler.
  • But, if an object member does not define a default constructor, a non-trivial default constructor synthesizes by a compiler for respective classes.
  • Moreover, in the case of inheritance, the constructor calling sequence starts from base(top-down) to derived manner. Constructor synthesis & augmentation remain same as above.
  • So in the above case, if you derive Bar from Base then constructor calling sequence would be Base -> Foo -> Bar.

How & Where Destructor Code Transform/Synthesize With Inheritance & Composition Class?

  • In case of the destructor, calling sequence is exactly the reverse that of a constructor. Like in the above case it would be Bar -> Foo -> Base. Synthesis & augmentation remain same as above. Access and all other things remain the same.

How & Where Virtual Table Code Will Be Inserted?

  • The virtual table code will be inserted by the compiler before & after the user-written code in constructor & destructor. That too on demand of user implementation.
  • Additionally, for the question “How virtual table code will be inserted”, my answer is “this is purely compiler dependent”. C++ standard only mandates behaviour. Although this would not be complex. It probably would look like:
 this->_vptr[0] = type_info("class_name"); 
  • By the way, I have written a more detailed article on virtual keyword here.


Do you like it☝️? Get such articles directly into the inbox…!?