views:

358

answers:

6

In C code like such:

{
   int i = 5;
   /* ....... */
}

The compiler will replace the code by moving the Stack pointer down (for stacks growing down) by the size of an int, and places the value 5 in that memory place.

Similarly, in C++ code, what does the compiler do if an object is created? For example:

class b
{
   public :
           int p;
           virtual void fun();
};

main()
{
   b   obj;
}

What will the compiler do for the above code? Can anyone explain when memory is allocated, and when memory for the virtual table is allocated, and when the default constructor is called?

+3  A: 

It's semantically the same, the stack pointer gets decremented (for stacks growing down) by sizeof b, then the default constructor is called to set up your instance.

In practice, depending on your architecture and on your compiler (and the flags you pass to it), basic types like in your int example may not get allocated actual memory space on the stack unless it's really required. They'll live in registers until an operation requiring a real memory address is needed (like the & operator).

Carl Norum
Depends on your processor. If you only have 6 GP registers (x86), variables will often be on the stack.
erikkallen
+1 @erikkallen. Absolutely agreed - it depends on how complicated your function is, too. On ARM there are lots of GP registers and most simple functions make no stack use at all.
Carl Norum
It may also depend on the optimization settings of the compiler and the lifetime of the variable whether it gets put on the stack.
Daniel Brotherston
Well put, I've edited to be less unilateral about it.
Carl Norum
Martin York
That's clearly not irrelevant; what if I'm on an embedded system with limited RAM and I want to squash my stack to as small as possible?
Carl Norum
@Carl: Its irrelevant to this question. The stack at the language level is an abstract space. Yes the compiler may use registers as part of the stack. Buts thats irrelavant to the program. It does not care where the stack is physically implemented.
Martin York
Can't argue with that I guess.
Carl Norum
+2  A: 

To touch on question about when the virtual table get's allocated. Usually it does done at compile time (though it does depend on the compiler).

The virtual table is static for any given class. Because of this the compiler can emit the table at compile time. During the initialization of the class the pointer to the virtual table is set to the stored table.

Because of this different instances of the same class will point to the same virtual table.

Foxeris
+1  A: 

On

   b   obj;

as with an int, the stack pointer is increased by the size of b. Then the constructor is called. The constructor may or may not call new or any other function to allocate memory. Thats up to the b's implementation. The call itself does not initiate any allocation.

The vftable is a static object. It is not created with the object itself. The object rather contains a 'invisible' pointer that points to its matching vftable. Its size is include in sizeof(b).

RED SOFT ADAIR
Note that when there is no constructor, the compiler is likely to generate and inline it. In this case the constructor has nothing to do, so by inlining it, it is in fact elided entirely.
bdonlan
@ bdonlan: Inline is red-hearing and not usefull in this context. Weather the constructor is generatod or defined by the user is not relevant (There will be one). The constructor has a lot to do. It calls the base class constructor initializes all the member variables (in this particular instance this is nothing but in the general case your statement is misleading). And at some point it may need to initialise the pointer to the vtable.
Martin York
A: 

Just to add to previous answers, once the object is constructed, the compiler will do whatever magic is necessary under it's conventions to guarantee the destructor is called when the object goes out of scope. The language guarantees this, but most compilers have to do something to follow through on the guarantee (like set up a table of pointers to destructors and rules about when to invoke the various destructors for the various objects).

Max Lybbert
+5  A: 

On Constructions

Logically there is no difference between the two:

In both case the stack is made large enough to hold the obect and the constructor is called on the object.

Just note:

  • The constructor for a POD type does nothing.
  • A user defined type with no constructor has a compiler generated default cosntructor.

You can think about it like this:

int   x;  // stack frame increased by sizeof(int) default construct (do nothing)
B     a;  // stack frame increased by sizeof(B)   default construct.

While:

int   y(6);  // stack frame increased by sizeof(int) Copy constructor called
B     b(a);  // stack frame increased by sizeof(B)   Copy constructor called

Ok. Of course the constructor for POD types is very trivial and the compiler will do a lot of optimizations (and may all but remove any actual code and even the memory address), but logically it is just fine to think of it happining this way.

Note: All types have a copy constructor (the compiler defines one if you don't) and the POD types you can logically think of it as copy construcion without any problems.

As for virtual tables:

Let me first note this is an implementation detail and not all compilers use them.
But the vtable itself is usually generated at compile time. Any object that needs a vtable has an invisable pointer added to the structure (this is included as part of the objects size). Then during contruction the pointer is set to point at the vtable.

Note: It is impossable to define when the vtable is set as this is not defined by the standard and thus each compiler is free to do it at any time. If you have a multiple level hierarchy then the vtable is probably set by each constructor from base to most derived and thus probably wrong until the final constructor finishes.

Note: You can not call virtual functions in the constructor/destructor. So all you can say is that the vtable will be correctly initialised only after the constructor has fully completed.

Martin York
A: 

According to Itanium C++ ABI standard (which, for example, GCC follows), virtual table is stored into a separate memory, global to the translation unit.

For each dynamic class a virtual table is constructed and is stored under specific name in the object file, like _ZTV5Class. Classes, whose runtime type is exactly Class will contain pointers to this table. These pointers will be initialized, adjusted and accessed, but no class contains its virtual table within its instance.

So the answer is that virtual tables are allocated at compile time, and during construction only pointers to them are set up.

Pavel Shved