3 ms·
> a C++ class is like a C struct that can contain function pointers. No, it's not. Calling an ordinary class member function in C++ has exactly the same overhe
by nly 9y ago
> a C++ class is like a C struct that can contain function pointers.
No, it's not. Calling an ordinary class member function in C++ has exactly the same overhead as calling a function in C. Even virtual functions in C++ are not the same as putting function pointers in a C struct (they live in a separate data structure called the vtable).
> the protection mechanisms and the class heirarchy
All C++ protection mechanisms occur at compile time and have no runtime overhead. Non-virtual inheritance hierarchies have the same overhead as C struct composition (because under the covers the memory layout is the same).
- cperciva 9y agoCalling an ordinary class member function in C++ has exactly the same overhead as calling a function in C. Modern compilers make the same optimization for function pointers which are only ever set to one value, too.
- nly 9y agoHi Colin. This isn't an optimisation though, it's a guarantee. Member function calls are resolved statically at compile-time. Replacing indirect calls off a function pointer with direct calls (devirtualization) is an optimisation that applies to both languages equally and requires whole-program / link-time optimization.
- khitchdee 9y agoDoesn't a vtable imply an extra level of indirection? You have to find where the vtable is in the object, then the function within the vtable, right? Is that not slower?
- mcguire 9y agoYes, although (cache behavior notwithstanding) it's a single pointer indirection that can frequently be optimized away by the compiler.
- khitchdee 9y agoMy point is simply this -- adding protection mechanisms and inheritance to classes neccesitates adding more complexity to the structure used to represent them (such as a vtable) which does add performance overheads. If you dont need those features, you can go leaner and faster with a C structure that includes function pointers to give you the basic packaging of data and functions that an object has.
- nly 9y agoIn common implementations the vtable pointer is always the first word inside the object. Given an arbitrary pointer to an object, the offset of this vtable pointer relative to what you're pointing to is always computed statically at compile time. Unless you're using multiple inheritance, this offset is usually zero because derived object pointers in a single-inheritance hierarchy actually always point to their base. If you're using multiple inheritance then an object can have multiple vtable pointers, but again which one you need to use is known at compile-time based on which class the virtual function you're calling is declared within, and the type of pointer you have. Once you have the vtable you then have to locate the function pointer for the function you're calling. Again, this is usually a compile-time constant offset from the start of the vtable. This ceases to be true when you have 'virtual inheritance' (not to be confused with virtual functions), when another indirection to find this function pointer is required. Here are some examples: https://godbolt.org/g/N2XcV7 https://godbolt.org/g/N2XcV7 You'll notice that the get_square() function, which returns a member function pointer to the virtual square function, doesn't even return any memory addresses, just metadata and an offset