10

I know it might sound like a weird question, but I was just wondering if class in C++ weights more than a struct with the same data fields, and there's this one thing I couldn't find an answer for...
Consider this:

struct SomeStruct {
    int a;
    int b;
};

class SomeClass {
public:
    SomeClass():a(0),b(0){}
private:
    int a;
    int b;
};

int main() {
    std::cout<<sizeof(SomeStruct)<<std::endl; // output is 8
    std::cout<<sizeof(SomeClass)<<std::endl; // output is 8
}

But now see what happens when I add a destructor to SomeClass:

struct SomeStruct {
    int a;
    int b;
};

class SomeClass {
public:
    SomeClass():a(0),b(0){}
    virtual ~SomeClass(){}
private:
    int a;
    int b;
};

int main() {
    std::cout<<sizeof(SomeStruct)<<std::endl; // output is 8 bytes
    std::cout<<sizeof(SomeClass)<<std::endl; // output is 16 bytes!
}

Why does SomeClass need 8 more bytes for the destructor?

Michael Gazonda
  • 2,720
  • 1
  • 17
  • 33
so.very.tired
  • 2,958
  • 4
  • 41
  • 69
  • 9
    You added a virtual function that requires a pointer to the virtual table (vtable). – djikay Jul 11 '14 at 18:47
  • 1
    The correct answer has already been given, but I wanted to add that the fact that you needlessly made the destructor virtual looks like an application of the "all destructors must be virtual" guideline which certain programmers apparently thought was a good idea 10-20 years ago. It's a really bad idea. – Christian Hackl Jul 11 '14 at 19:21
  • 1
    @Christian - could you please expand on that? Why is it a *really* bad idea? – Michael Gazonda Jul 12 '14 at 00:13
  • @ChristianHackl, Eclipse automatically generated it for me as virtual... – so.very.tired Jul 12 '14 at 09:40
  • 2
    Making a destructor virtual where none is needed may easily double an object's size, and it gives programmers the wrong impression that the class is meant to be derived from. It creates confusion and undermines the important design-wise distinction between value classes and classes with identity. It's just a really useless guideline which attempts to solve a problem that does not exist for experienced programmers and is only a symptom of real problems in beginners' class designs. – Christian Hackl Jul 13 '14 at 08:13

3 Answers3

18

The size increase is because of virtual. If you don't make the destructor virtual, you won't see the size increase.

So, it's not the destructor that makes your type bigger, but rather it's adding a virtual function that's doing it.

The 8 extra bytes in question is a pointer to the virtual table (vtable) for the class you are using. As noted in the comments, this is a "one time" cost. Adding one virtual function to a class brings on this cost, but you don't see that cost with additional virtual functions.

Edit:

The additional size in the class will depend on whether this is compiled as a 32 bit or 64 bit program. The link to the virtual table takes 4 extra on 32bit, and 8 extra bytes on a 64bit platform.

naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259
Michael Gazonda
  • 2,720
  • 1
  • 17
  • 33
  • 1
    It's worth noting you pay this price once if you have any virtual functions. After that the rest don't cost anything. – tadman Jul 11 '14 at 18:48
  • @so.very.tired Adding a class's **first** virtual function will increase the size, because a pointer to a [vtable](http://en.wikipedia.org/wiki/Virtual_method_table) will have been added to each object instance. – Drew Dormann Jul 11 '14 at 18:48
  • I see... So why is adding more virtual functions to the class did not increase its size even more? wouldn't you need a pointer for each virtual function? – so.very.tired Jul 11 '14 at 18:51
  • 1
    You're thinking that the other virtual functions require pointers as well, and you'd be right. Those pointers are the same for each instance of your class though, and so the implementation only needs one pointer to link to a table of pointers that lists each virtual function's address. So to sum up - it's a pointer to a list of pointers. – Michael Gazonda Jul 11 '14 at 18:55
  • @so.very.tired http://stackoverflow.com/questions/10065088/how-vtable-of-virtual-functions-work might help a bit. A `virtual` methods are a property of the class, the class instance just needs a pointer to its class table. – Yakk - Adam Nevraumont Jul 11 '14 at 19:25
4

It's not the fact that you added a destructor. It's the fact that you added a virtual method (additional virtual methods would incur no additional per-instance cost). Most (all?) C++ implementations use a virtual function pointer table to enable dynamic dispatch, and this requires a pointer to the appropriate table to be stored within each object. This pointer-to-virtual-table is the extra space per object you're seeing.

Mark B
  • 95,107
  • 10
  • 109
  • 188
0

When you declare a destructor as virtual the compiler automatically adds a vtable pointer as a member in your class. This is necessary so it can find the address of all the destructors of the classes derived from yours.

This new member (which you cannot access trivially, neither should you) is added into your class and thus increases its size by the size of a trivial raw pointer, which is usually the same size as an int but may depend on your architecture.

  • 1
    The pointer size may not have the same size as an int. Therefore, I think you could improve on that sentence. Otherwise a good answer. – user2672165 Jul 11 '14 at 20:08