Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding a first virtual function to a class

Tags:

c++

What happens when you add a first virtual function to a class in terms of its memory consumption, object layout, and so on? How much slower are virtual functions than normal functions?

like image 329
ltnewberry Avatar asked Oct 30 '22 04:10

ltnewberry


1 Answers

If you really care I suggest testing it on your own compiler & system, as it may produce different results. Here is an example I used:

#include <iostream>

template<typename B> struct Base { B b; void f() {}; };
template<typename B> struct Base_Virtual { B b; virtual void f() {}; };
template<typename B> struct Base_Pointer { B b; void* p; };

#define PRINT_ALIGNOF_SIZEOF(T) std::cout << "sizeof(" #T ") = " << sizeof(T) << ", alignof(" #T ") = " << alignof(T) << std::endl
int main()
{
    PRINT_ALIGNOF_SIZEOF(char);
    PRINT_ALIGNOF_SIZEOF(Base<char>);
    PRINT_ALIGNOF_SIZEOF(Base_Virtual<char>);
    PRINT_ALIGNOF_SIZEOF(Base_Pointer<char>);
    std::cout << std::endl;
    PRINT_ALIGNOF_SIZEOF(void*);
    PRINT_ALIGNOF_SIZEOF(Base<void*>);
    PRINT_ALIGNOF_SIZEOF(Base_Virtual<void*>);
    PRINT_ALIGNOF_SIZEOF(Base_Pointer<void*>);

    std::cin.ignore();
}   

Which produced the following output (with Windows 10 / Visual C++ 14.0 compiled as an ‘x64’ program)

sizeof(char) = 1, alignof(char) = 1
sizeof(Base<char>) = 1, alignof(Base<char>) = 1
sizeof(Base_Virtual<char>) = 16, alignof(Base_Virtual<char>) = 8
sizeof(Base_Pointer<char>) = 16, alignof(Base_Pointer<char>) = 8

sizeof(void*) = 8, alignof(void*) = 8
sizeof(Base<void*>) = 8, alignof(Base<void*>) = 8
sizeof(Base_Virtual<void*>) = 16, alignof(Base_Virtual<void*>) = 8
sizeof(Base_Pointer<void*>) = 16, alignof(Base_Pointer<void*>) = 8

This suggests that adding a virtual function to a class is equivalent to adding a void* member at the end. (Note: adding more virtual functions did not change the result).

As a general rule of thumb, only add virtual functions if they are useful (though adding a virtual destructor is considered best practice if your class is going to be used in hierarchies, even if it is always trivial).

like image 80
Isaac Avatar answered Nov 02 '22 09:11

Isaac