On 22 October 2014 17:16, Martin Liška <mli...@suse.cz> wrote: > On 10/22/2014 05:30 PM, Jonathan Wakely wrote: >> >> On 22 October 2014 16:15, Martin Liška wrote: >>> >>> Hello. >>> >>> I've been playing with following example: >>> >>> #include <stdlib.h> >>> >>> class Base >>> { >>> public: >>> virtual ~Base() {} >>> }; >>> >>> class Derived: public Base >>> { >>> }; >>> >>> #define N 1000 >>> >>> int main() >>> { >>> Base **b = (Base **)malloc (sizeof(Base *) * N); >>> for (unsigned i = 0; i < N; i++) >>> b[i] = new Derived(); >>> >>> for (unsigned i = 0; i < N; i++) >>> delete b[i]; >>> >>> return 0; >>> } >>> >>> Where I would like to somehow give an advice to devirtualize machinery. >>> My >>> motivation is to inline destruction in 'delete b[i]'. >>> 'final' keyword does not solve my problem: >>> >>> a.c:9:7: error: virtual function ‘virtual Derived::~Derived()’ >>> class Derived: public Base >>> ^ >>> a.c:6:11: error: overriding final function ‘virtual Base::~Base()’ >>> virtual ~Base() final {} >> >> >> Virtual destructors are special, derived classes *must* override them, >> so you can't make it final in the base class. >> >>> If I enclose my classes to anonymous namespace: >>> >>> Procesing function int main()/172 >>> Targets of polymorphic call of type 0:struct Base token 2 >>> Contained in type:struct Base at offset 0 >>> This is a complete list. (derived types included) >>> virtual {anonymous}::Base::~Base()/164 virtual >>> {anonymous}::Derived::~Derived()/183 >>> >>> More than one likely target >> >> >> Presumably because the dynamic type of *b[i] could be Base or Derived, >> and the compiler can't know until it checks it. Does it make any >> difference if you make Base an abstract class? In that case the >> compiler should know that the dynamic type of *b[i] cannot be Base, so >> must be a Derived. > > > > Looks that addition of an abstract method to Base class really helps: > > for (unsigned i = 0; i < N; i++) > delete b[i]; > 4006a0: 48 8b 3b mov (%rbx),%rdi > 4006a3: 48 85 ff test %rdi,%rdi > 4006a6: 74 05 je 4006ad <main+0x4d> > public: > virtual ~Base() {} > virtual void Foo() = 0; > }; > > class Derived final: public Base > 4006a8: e8 83 ff ff ff callq 400630 <_ZdlPv@plt> > 4006ad: 48 83 c3 08 add $0x8,%rbx
Cool, that's what I expected. However, if you have more than one type that inherits from Base and either Derived or Derived2 has a non-trivial destructor then it probably won't help, as the compiler still needs to do a check to see which destructor to call. And if you don't have more than derived type why are you using polymorphism in the first place? i.e. I expect it will only help with pointless examples, not real code.