Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are methods duplicated in memory for every instance of an object? If so, can this be avoided?

Say I have an object that exists in high quantity, stores little data about itself, but requires several larger functions to act upon itself.

class Foo
{
public:
    bool is_dead();

private:
    float x, y, z;
    bool dead;
    void check_self();
    void update_self();
    void question_self();
};

What behavior can I expect from the compiler - would every new Foo object cause duplicates of its methods to be copied into memory?

If yes, what are good options for managing class-specific (private-like) functions while avoiding duplication?

If not, could you elaborate on this a little?

like image 744
Adrian Avatar asked Jul 26 '14 12:07

Adrian


1 Answers

C++ methods are simply functions (with a convention about this which often becomes the implicit first argument).

Functions are mostly machine code, starting at some specific address. The start address is all that is needed to call the function.

So objects (or their vtable) need at most the address of called functions.

Of course a function takes some place (in the text segment).

But an object won't need extra space for that function. If the function is not virtual, no extra space per object is needed. If the function is virtual, the object has a single vtable (per virtual class). Generally, each object has, as its first field, the pointer to the vtable. This means 8 bytes per object on x86-64/Linux. Each object (assuming single inheritance) has one vtable pointer, independently of the number or of the code size of the virtual functions.

If you have multiple, perhaps virtual, inheritance with virtual methods in several superclasses you'll need several vtable pointers per instance.

So for your Foo example, there is no virtual function (and no superclass containing some of them), so instances of Foo contain no vtable pointer.

If you add one (or many hundreds) of virtual functions to Foo (then you should have a virtual destructor, see rule of three in C++), each instance would have one vtable pointer.

If you want a behavior to be specific to instances (so instances a and b could have different behavior) without using the class machinery for that, you need some member function pointers (in C++03) or (in C++11) some std::function (perhaps anonymous closures). Of course they need space in every instance.

BTW, to know the size of some type or class, use sizeof .... (it does include the vtable[s] pointer[s] if relevant).

like image 72
Basile Starynkevitch Avatar answered Sep 24 '22 19:09

Basile Starynkevitch