39

The question is pretty straight forward. For clarity, consider the example below:

// Note that none of the class have any data members
// Or if they do have data members, they're of equal size, type, and quantity
class Foo {
public:
    void foo1();
    void foo2();
    // 96 other methods ...
    void foo99();
};

class Bar {
public:
    // Only one method
    void bar();
};

class Derived1 : public Foo { };
class Derived2 : public Bar { };

int main() {
    Foo f;
    Bar b;
    Derived1 d1;
    Derived2 d2;
    return 0;
}

Do instances f, b, d1, and d2 all occupy the same amount of space in memory? As an extension to this question, would copying instances of Foo when passing it around take longer than Bar, theoretically?

Zeenobit
  • 4,954
  • 3
  • 34
  • 46

4 Answers4

33

Only instance data increases the size of instances of a class (in all implementations that I know of), except that if you add virtual functions or inherit from a class with virtual functions then you take a one-time hit for a v-table pointer.

Also, as someone else correctly mentions the minimum size of a class is 1 byte.

Some examples:

// size 1 byte (at least)
class cls1
{
};

// size 1 byte (at least)
class cls2
{
    // no hit to the instance size, the function address is used directly by calling code.
    int instanceFunc();
};

// sizeof(void*) (at least, for the v-table)
class cls3
{
    // These functions are indirectly called via the v-table, a pointer to which must be stored in each instance.
    virtual int vFunc1();
    // ...
    virtual int vFunc99();
};

// sizeof(int) (minimum, but typical)
class cls4
{
    int data;
};

// sizeof(void*) for the v-table (typical) since the base class has virtual members.
class cls5 : public cls3
{
};

Compiler implementations may handle multiple virtual inheritance with multiple v-table pointers or other other methods, so these too will have effect on the class size.

Finally, member data alignment options can have an impact. The compiler may have some option or #pragma to specify that member data should have a starting address that is a multiple of the number of bytes specified. For example, with alignment on 4 byte boundaries and assuming sizeof(int) = 4:

// 12 bytes since the offset of c must be at least 4 bytes from the offset of b. (assuming sizeof(int) = 4, sizeof(bool) = 1)
class cls6
{
    int a;
    bool b;
    int c;
};
Codie CodeMonkey
  • 7,669
  • 2
  • 29
  • 45
  • Closer, but empty types usually take at least one byte. There's few compilers that will make these less than one byte. – Mooing Duck Nov 08 '11 at 23:01
  • 4
    @MooingDuck It has to be at least one byte on byte-addressable machines, so that two objects cannot have the same address. The compiler doesn't get to decide. (Stroustrup wrote this somewhere which is where I read it, can't remember where though.) – Seth Carnegie Nov 08 '11 at 23:05
  • @SethCarnegie: Yes, but the standard _also_ says that the compiler can break all the rules as long as it makes the same IO calls and volatile read/writes in the same order with the same parameters, which allows GCC to sometimes make objects less than one byte, as long as that doesn't change the execution of the program. – Mooing Duck Nov 08 '11 at 23:10
  • @MooingDuck, thanks for pointing out the 1-byte. I've edited the answer with a few examples. – Codie CodeMonkey Nov 08 '11 at 23:13
  • @SethCarnegie: found it: http://www.gotw.ca/publications/mill07.htm Sometimes empty base classes are 0 bytes. – Mooing Duck Nov 08 '11 at 23:18
  • @MooingDuck You're right, you said "empty types," but I thought you meant/misread it as instances, which are completely different things. – Seth Carnegie Nov 08 '11 at 23:22
  • For completion, virtual inheritance does also have an impact on the size of the instances (requires a pointer to each virtual base, don't quite remember if anything else) – David Rodríguez - dribeas Nov 08 '11 at 23:33
  • @David: I don't think virtual inheritance adds to the instance size in most implementations, just the length of the v-table. However, in most multiple inheritance does affect the instance size (it's a detail left to the compiler), so I'll mention that, thanks. – Codie CodeMonkey Nov 09 '11 at 00:53
  • @DeepYellow: Virtual inheritance does add extra space requirements. In non-virtual inheritance given a pointer to the derived type, the location of the base type is known (the layout is fixed), but with virtual inheritance, the relative location of the base with respect to the derived object can change at different levels of the hierarchy. The compiler needs to add extra data to know how to get to the base class from the derived class. On the other hand, multiple inheritance does not need to add extra space (other than to hold the bases). – David Rodríguez - dribeas Nov 09 '11 at 08:08
  • This is just a test in one compiler, but you can reproduce it in other compilers just to check: http://www.ideone.com/yreND. – David Rodríguez - dribeas Nov 09 '11 at 08:47
9

Strickly speaking, this is implementation dependent. But the number of methods should not change the size of class objects. For non-virtual methods, there is nothing inside the object memory that relates to method pointers. If you have virtual methods, then each object has a single pointer to a vtable. The vtable grows when you add more methods, but the pointer size stays the same.

Further info: for non-virtual methods, the compiler tracks method pointers for each class. when you call a non-virtual method, the compiler passes a pointer to the method that points to the object, either as a hidden parameter, or on the stack. This is how a method 'knows' its object and has access the this pointer. For virtual methods, the method pointer is actually an index into the vtable, so the compiler passes this to the dereferenced entry in the vtable.

ThomasMcLeod
  • 7,603
  • 4
  • 42
  • 80
  • for non-virtual methods, the compiler tracks method pointers for each class. Is this a tradeoff which Sacrifice time for space? – Djvu Sep 02 '14 at 13:24
  • @Djvu, no, non-virtual methods are more efficient in both time and space. – ThomasMcLeod Sep 03 '14 at 13:47
3

Yes they will. Actually in your case the size will be 1. In C++ a class even without any data member will have a size of 1.

FailedDev
  • 26,680
  • 9
  • 53
  • 73
1

Foo and Bar should each be one byte. Derived1 and Derived2 might be one or two bytes.

The reason is the compiler stores all static information in the executable code, including all member functions. Where your code calls foo1 on an instance of Foo, it just calls Foo::foo1(this), which is the same for every Foo in the program. virtual functions are an exception, but do not add additional size per member function, only a one-time additional size (usually 4/8 bytes) if there's any virtual functions at all.

Mooing Duck
  • 64,318
  • 19
  • 100
  • 158