dynamic_cast expensive?

Discussion in 'C++' started by cppquester, Apr 24, 2010.

  1. cppquester

    cppquester Guest

    When I replaced the dynamic cast in the code excerpt below
    (here each class knows it type), I gained a speedup of about factor
    4(!)
    (in release mode (-O2))

    Why is a dynamic cast so expensive? I thought basically the RTTI
    system basically does
    what I did (store the type (implicitely) and then cast or return
    NULL).

    Or might this be specific to my platform (g++ 4.2.4)?

    Thanks,
    Marc


    thisType* lEnd=dynamic_cast<thisType*>(derived);
    if( lEnd == NULL)
    throw MyException("Type changed.");*/


    if( derived->Type() != this->type)
    throw MyException("Type changed.");
    thisType* lEnd=static_cast<thisType*>(derived);
    cppquester, Apr 24, 2010
    #1
    1. Advertising

  2. * cppquester:
    > When I replaced the dynamic cast in the code excerpt below
    > (here each class knows it type), I gained a speedup of about factor
    > 4(!)
    > (in release mode (-O2))
    >
    > Why is a dynamic cast so expensive? I thought basically the RTTI
    > system basically does
    > what I did (store the type (implicitely) and then cast or return
    > NULL).


    No, that's not what it does. Your alternative code suggests that you
    think that a dynamic_cast<T> will fail if the supplied pointer is not
    pointing at an instance of type T. It's slightly more complex than
    that.

    Consider the following example:

    class object { ... };

    class rectangle : public object { ... };

    class square : public rectangle { ... };

    square mySquare;
    object* squarePtr = &mySquare;

    Both the dynamic cast and your approach will work for a cast to square*.
    However, yours will *fail* for a cast to rectangle*, whereas the
    dynamic_cast<> will work. Things get increasingly complex if you take
    multiple inheritance into consideration. Either way, dynamic_cast<> may have
    to traverse the entire inheritance tree in order to determine success or
    failure, and this may indeed turn out to be expensive - especially if you
    have a significant amount of classes derived from a common base class.

    Bottom line: Your Type() based approach will only work for *exact* matches,
    not for casts to an intermediate base class.

    > Or might this be specific to my platform (g++ 4.2.4)?


    No.

    > thisType* lEnd=dynamic_cast<thisType*>(derived);
    > if( lEnd == NULL)
    > throw MyException("Type changed.");*/


    This also means that the above test is possibly flawed. It wouldn't
    generate an exception in case 'derived' points to an object that is
    -derived- from thisType (but not a thisType itself). Your choice of
    variable names is slightly confusing, so I'm not really sure that's
    what you want.

    > if( derived->Type() != this->type)
    > throw MyException("Type changed.");
    > thisType* lEnd=static_cast<thisType*>(derived);


    You coud use a typeid() keyword for a more standard approach; something
    along the line of

    if (std::typeid(derived) != std::typeid(type))
    ...

    Note that there's a performance issue lurking here too; while
    std::typeid() is constant order (as opposed to dynamic_cast<>), comparing
    the std::type_info resulting from the calls to std::typeid() may be
    expensive. While it is implementation-defined, it'll most likely contain
    the typename as a (not necessarily human-readable) string, which makes
    comparison not cheap either.

    There are a few workarounds floating around, using pointers to
    std::type_info instead, but that smells like undefined behaviour. I know
    from own experience that this trick will most likely not work for libraries.

    --
    Martijn van Buul -
    Martijn van Buul, Apr 24, 2010
    #2
    1. Advertising

  3. cppquester

    Salt_Peter Guest

    On Apr 24, 12:16 pm, cppquester <> wrote:
    > When I replaced the dynamic cast in the code excerpt below
    > (here each class knows it type), I gained a speedup of about factor
    > 4(!)
    > (in release mode (-O2))
    >
    > Why is a dynamic cast so expensive? I thought basically the RTTI
    > system basically does
    > what I did (store the type (implicitely) and then cast or return
    > NULL).
    >
    > Or might this be specific to my platform (g++ 4.2.4)?
    >
    > Thanks,
    > Marc
    >
    >   thisType* lEnd=dynamic_cast<thisType*>(derived);
    >   if( lEnd == NULL)
    >     throw MyException("Type changed.");*/
    >
    >   if( derived->Type() != this->type)
    >     throw MyException("Type changed.");
    >   thisType* lEnd=static_cast<thisType*>(derived);


    Not enough info.
    A class always knows its type, you don't need RTTI for that. In the
    case where the object 'derived' above is of a type which is a
    derivative of thisType, then derived will always be of type thisType.
    So doing a dynamic cast is pointless, doing any cast is pointless.

    So to answer your question: the question is irrelevant.

    Btw, C++ programmers are reknown to be pathetic when it comes to
    guessing. Try making a simple, short compileable example to explain
    what you seek.

    class thisType { };
    class Derived : public thisType { };

    int main()
    {
    // do stuff
    }
    Salt_Peter, Apr 24, 2010
    #3
  4. cppquester

    cppquester Guest

    On 24 Apr., 21:25, Salt_Peter <> wrote:
    > On Apr 24, 12:16 pm, cppquester <> wrote:
    >
    >
    >
    > > When I replaced the dynamic cast in the code excerpt below
    > > (here each class knows it type), I gained a speedup of about factor
    > > 4(!)
    > > (in release mode (-O2))

    >
    > > Why is a dynamic cast so expensive? I thought basically the RTTI
    > > system basically does
    > > what I did (store the type (implicitely) and then cast or return
    > > NULL).

    >
    > > Or might this be specific to my platform (g++ 4.2.4)?

    >
    > > Thanks,
    > > Marc

    >
    > >   thisType* lEnd=dynamic_cast<thisType*>(derived);
    > >   if( lEnd == NULL)
    > >     throw MyException("Type changed.");*/

    >
    > >   if( derived->Type() != this->type)
    > >     throw MyException("Type changed.");
    > >   thisType* lEnd=static_cast<thisType*>(derived);

    >
    > Not enough info.
    > A class always knows its type, you don't need RTTI for that. In the
    > case where the object 'derived' above is of a type which is a
    > derivative of thisType, then derived will always be of type thisType.
    > So doing a dynamic cast is pointless, doing any cast is pointless.
    >
    > So to answer your question: the question is irrelevant.
    >
    > Btw, C++ programmers are reknown to be pathetic when it comes to
    > guessing. Try making a simple, short compileable example to explain
    > what you seek.
    >
    > class thisType { };
    > class Derived : public thisType { };
    >
    > int main()
    > {
    >   // do stuff
    >
    > }
    >
    >



    You are right, it was not clear.
    Actually the following was meant:

    class Base { virtual int Type(); ...};

    class thisType: public Base { int t; int Type(){ return t;} ...};
    class Derived : public Base { int t; int Type(){ return t;} ...};
    cppquester, Apr 25, 2010
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. John Dalberg

    Least expensive server pdf control?

    John Dalberg, Sep 15, 2005, in forum: ASP .Net
    Replies:
    0
    Views:
    358
    John Dalberg
    Sep 15, 2005
  2. Mickey Segal
    Replies:
    3
    Views:
    2,279
    Mickey Segal
    Jul 10, 2003
  3. Replies:
    3
    Views:
    2,916
    Thomas Hawtin
    Dec 11, 2005
  4. Monster

    how are exception expensive?

    Monster, Apr 29, 2004, in forum: C++
    Replies:
    3
    Views:
    779
    jeffc
    Apr 30, 2004
  5. Steven T. Hatton

    Will this be hard/expensive to inline?

    Steven T. Hatton, Oct 2, 2004, in forum: C++
    Replies:
    2
    Views:
    382
    David Hilsee
    Oct 3, 2004
Loading...

Share This Page