6 ms·
I dunno why people downvote this comment, it seems legit and it's important to know that `inline`, `virtual`, and `constexpr` are actually just heuristics / sug
by mshockwave 5y ago
I dunno why people downvote this comment, it seems legit and it's important to know that `inline`, `virtual`, and `constexpr` are actually just heuristics / suggestions to compilers.
- jeffbee 5y agoInline is probably the keyword with true definition furthest from popular belief. By the way, constexpr implies inline, for function declarations.
- jcelerier 5y ago> it seems legit and it's important to know that `inline`, `virtual`, and `constexpr` are actually just heuristics / suggestions to compilers. but they are not ? - inline relaxes ODR which generally changes the linkage of the symbol (weak linkage when inline & exported, strong when not) - adding virtual will always make your class have a vtable and your method overridable. - constexpr make it possible to use in e.g. template arguments: constexpr int foo() { return 123; } std::array<int, foo()> arr; that does not mean that the compiler cannot optimize - no matter how complex your program is, if the compiler has sufficiently advanced optimization passes, it should be able to precompute everything that is possible at compile time
- jeffbee 5y ago> adding virtual will always make your class have a vtable No? https://godbolt.org/z/qMzY1h6Gs https://godbolt.org/z/qMzY1h6Gs
- adamrezich 5y agowow, I never knew that, crazy
- jeffbee 5y agoThis example is trivial but compilers are generally very good at de-virtualizing at compile time even in large programs. People who bring up the supposed cost of vtable dispatch are usually either repeating bad folk wisdom, or haven't used the language since 20 years ago.
- adamrezich 5y agoseems to me like the real problem is the burden of knowledge required to intuit how C++ compilers will or won't optimize the code you write. I know this has been an ongoing refrain for years now but this sort of thing has driven me away from using C++ personally. I wish there was a better syntactic system for denoting where you do and don't want certain optimizations to be applied.
- jcelerier 5y agodo you also wonder where the JVM or .net runtime will inline method calls ?
- adamrezich 5y agono because those are explicitly "Managed" systems
- jcelerier 5y ago... but the object has a vtable in the exemple ? a call being optimized because the compiler can infer that a specific call site does not need a vtable, does not mean that the vtable isn't there taking up space in the object. proof: https://godbolt.org/z/W9MMGvTEz https://godbolt.org/z/W9MMGvTEz proof at runtime (to make sure that the compiler doesn't "lie" about the size, we check the stack address of the variable constructed after the one with a virtual, and after the one without ; in the first case it's 16 bytes after, in the second 1 byte): https://godbolt.org/z/s11o9do4n https://godbolt.org/z/s11o9do4n ; basically in the simplest indirect measure possible that we can make of the object's size, the vtable is there
- chrisseaton 5y agoIf your class never needs a runtime virtual call because all virtual calls were monomorphisable, why would it still include a virtual table? What’s the point?
- jcelerier 5y ago> If your class never needs a runtime virtual call because all virtual calls were monomorphisable, why would it still include a virtual table? What’s the point? if that was not the case, it would mean that the size of the type would vary, which would break a lot of expectations. Imagine the following: class obj { virtual int space_used() { return sizeof(obj); } }; class sub1 : obj { int space_used() override { return sizeof(sub1); } }; it would be very normal for someone to call `space_used();` at some point, and use that size at another point (with a different instance), for instance for allocation ; if that size was to change because that instance was "optimized" by the compiler, that could wreak havoc.
- chrisseaton 5y agoAh I assumed it knew about all classes before it started running compile-time code.
- jeffbee 5y agoIt doesn't have a vtable, it has enough space for vptr, but vptr isn't even initialized. It's true that thing is larger than your trivial class.
- hermitdev 5y agoIt's also worth noting that a vtable implementation of `virtual` methods is not required by the standard. Granted, I'm not aware of any other implementations of virtual methods (in the case where the compiler cannot optimize the virtual dispatch) in production compilers.
- Kranar 5y agoGCC can use whole program optimization to replace virtual dispatch with a series of if statements. There are plenty of situations where it's faster to test for a handful of types and then inline the body than it is to perform two indirections.
- hermitdev 5y ago> GCC can use whole program optimization to replace virtual dispatch with a series of if statements. Would you happen to have a sharable example of this occurring? I'd be curious to see what heuristics GCC is using. Also, what the conditional is on...is it still on the vtable, but just avoiding the indirect call?
- Kranar 5y agoJan Hubička worked on much of the devirtualization in GCC and posted a blog about how it works here: http://hubicka.blogspot.com/2014/01/devirtualization-in-c-part-1.html http://hubicka.blogspot.com/2014/01/devirtualization-in-c-pa...
- gpderetta 5y agoTechnically virtual guarantees dynamic dispatch (i.e. calls through the base type will resolve to the derived function object). The dispatch can still be resolved at compile time of course. A compiler could legally remove the vpntr if not necessary. In practice this only happens for purely local objects as current compilers do not implement the necessary interprocedural data layout transformation.