Categories
c++ c++-faq casting pointers

When should static_cast, dynamic_cast, const_cast, and reinterpret_cast be used?

2912

What are the proper uses of:

How does one decide which to use in which specific cases?

4

  • 38

  • 4

    For some useful concrete examples of using different kind of casts, you can check the first answer on a similar question in this other topic.

    – TeaMonkie

    Feb 24, 2017 at 10:41


  • 4

    You can find really good answers for your question above. But I would like to put one more point here, @e.James “There is nothing that these new c++ cast operators can do and c style cast cannot. These are added more or less for the better code readability.”

    Oct 9, 2018 at 7:51


  • 1

    @BreakBadSP The new casts are not only for better code readability. They are there to make it harder to do do dangerous things, like casting away const or casting pointers instead of their values. static_cast has much less possibilities to do something dangerous than a c style cast!

    – FourtyTwo

    Jan 13, 2020 at 12:50

2898

static_cast is the first cast you should attempt to use. It does things like implicit conversions between types (such as int to float, or pointer to void*), and it can also call explicit conversion functions (or implicit ones). In many cases, explicitly stating static_cast isn’t necessary, but it’s important to note that the T(something) syntax is equivalent to (T)something and should be avoided (more on that later). A T(something, something_else) is safe, however, and guaranteed to call the constructor.

static_cast can also cast through inheritance hierarchies. It is unnecessary when casting upwards (towards a base class), but when casting downwards it can be used as long as it doesn’t cast through virtual inheritance. It does not do checking, however, and it is undefined behavior to static_cast down a hierarchy to a type that isn’t actually the type of the object.


const_cast can be used to remove or add const to a variable; no other C++ cast is capable of removing it (not even reinterpret_cast). It is important to note that modifying a formerly const value is only undefined if the original variable is const; if you use it to take the const off a reference to something that wasn’t declared with const, it is safe. This can be useful when overloading member functions based on const, for instance. It can also be used to add const to an object, such as to call a member function overload.

const_cast also works similarly on volatile, though that’s less common.


dynamic_cast is exclusively used for handling polymorphism. You can cast a pointer or reference to any polymorphic type to any other class type (a polymorphic type has at least one virtual function, declared or inherited). You can use it for more than just casting downwards – you can cast sideways or even up another chain. The dynamic_cast will seek out the desired object and return it if possible. If it can’t, it will return nullptr in the case of a pointer, or throw std::bad_cast in the case of a reference.

dynamic_cast has some limitations, though. It doesn’t work if there are multiple objects of the same type in the inheritance hierarchy (the so-called ‘dreaded diamond’) and you aren’t using virtual inheritance. It also can only go through public inheritance – it will always fail to travel through protected or private inheritance. This is rarely an issue, however, as such forms of inheritance are rare.


reinterpret_cast is the most dangerous cast, and should be used very sparingly. It turns one type directly into another — such as casting the value from one pointer to another, or storing a pointer in an int, or all sorts of other nasty things. Largely, the only guarantee you get with reinterpret_cast is that normally if you cast the result back to the original type, you will get the exact same value (but not if the intermediate type is smaller than the original type). There are a number of conversions that reinterpret_cast cannot do, too. It’s used primarily for particularly weird conversions and bit manipulations, like turning a raw data stream into actual data, or storing data in the low bits of a pointer to aligned data.


C-style cast and function-style cast are casts using (type)object or type(object), respectively, and are functionally equivalent. They are defined as the first of the following which succeeds:

  • const_cast
  • static_cast (though ignoring access restrictions)
  • static_cast (see above), then const_cast
  • reinterpret_cast
  • reinterpret_cast, then const_cast

It can therefore be used as a replacement for other casts in some instances, but can be extremely dangerous because of the ability to devolve into a reinterpret_cast, and the latter should be preferred when explicit casting is needed, unless you are sure static_cast will succeed or reinterpret_cast will fail. Even then, consider the longer, more explicit option.

C-style casts also ignore access control when performing a static_cast, which means that they have the ability to perform an operation that no other cast can. This is mostly a kludge, though, and in my mind is just another reason to avoid C-style casts.

20

  • 22

    dynamic_cast is only for polymorphic types. you only need to use it when you’re casting to a derived class. static_cast is certainly the first option unless you specifically need dynamic_cast’s functinoality. It’s not some miraculous silver-bullet “type-checking cast” in general.

    – jalf

    Dec 1, 2008 at 21:20

  • 3

    Great answer! One quick remark: static_cast might be necessary to cast up the hierarchy in case you have a Derived*& to cast into Base*&, since double pointers/references don’t automagically cast up the hierarchy. I came across such (frankly, not common) situation two minutes ago. 😉

    – bartgol

    Apr 8, 2013 at 15:16

  • 8

    *”no other C++ cast is capable of removing const (not even reinterpret_cast)”… really? What about reinterpret_cast<int *>(reinterpret_cast<uintptr_t>(static_cast<int const *>(0)))?

    Jan 15, 2015 at 11:33

  • 50

    I think an important detail missing above is that dynamic_cast has a run-time performance penalty compared to static or reinterpret_cast. This is important, e.g. in real-time software.

    – jfritz42

    Jul 30, 2015 at 0:55

  • 11

    May be worth mentioning that reinterpret_cast is often the weapon of choice when dealing with an API’s set of opaque data types

    Aug 4, 2015 at 13:09

395

  • Use dynamic_cast for converting pointers/references within an inheritance hierarchy.

  • Use static_cast for ordinary type conversions.

  • Use reinterpret_cast for low-level reinterpreting of bit patterns. Use with extreme caution.

  • Use const_cast for casting away const/volatile. Avoid this unless you are stuck using a const-incorrect API.

1

  • 11

    Be careful with dynamic_cast. It relies on RTTI and this will not work as expected across shared libraries boundaries. Simply because you build executable and shared library independly in there is no standardized way to sync RTTI across different builds. For this reason in Qt library there exists qobject_cast<> which uses the QObject type info for checking types.

    Oct 23, 2018 at 8:25


231

(A lot of theoretical and conceptual explanation has been given above)

Below are some of the practical examples when I used static_cast, dynamic_cast, const_cast, reinterpret_cast.

(Also referes this to understand the explaination : http://www.cplusplus.com/doc/tutorial/typecasting/)

static_cast :

OnEventData(void* pData)

{
  ......

  //  pData is a void* pData, 

  //  EventData is a structure e.g. 
  //  typedef struct _EventData {
  //  std::string id;
  //  std:: string remote_id;
  //  } EventData;

  // On Some Situation a void pointer *pData
  // has been static_casted as 
  // EventData* pointer 

  EventData *evtdata = static_cast<EventData*>(pData);
  .....
}

dynamic_cast :

void DebugLog::OnMessage(Message *msg)
{
    static DebugMsgData *debug;
    static XYZMsgData *xyz;

    if(debug = dynamic_cast<DebugMsgData*>(msg->pdata)){
        // debug message
    }
    else if(xyz = dynamic_cast<XYZMsgData*>(msg->pdata)){
        // xyz message
    }
    else/* if( ... )*/{
        // ...
    }
}

const_cast :

// *Passwd declared as a const

const unsigned char *Passwd


// on some situation it require to remove its constness

const_cast<unsigned char*>(Passwd)

reinterpret_cast :

typedef unsigned short uint16;

// Read Bytes returns that 2 bytes got read. 

bool ByteBuffer::ReadUInt16(uint16& val) {
  return ReadBytes(reinterpret_cast<char*>(&val), 2);
}

8

  • 39

    The theory of some of the other answers are good, but still confusing, seeing these examples after reading the other answers really makes them all make sense. That is without the examples, I was still unsure, but with them, I am now sure about what the other answers mean.

    – Solx

    Apr 29, 2014 at 14:41

  • 1

    About the last usage of reinterpret_cast: isn’t this the same as using static_cast<char*>(&val) ?

    May 27, 2016 at 11:55


  • 5

    @LorenzoBelli Of course not. Did you try it? The latter is not valid C++ and blocks compilation. static_cast only works between types with defined conversions, visible relation by inheritance, or to/from void *. For everything else, there are other casts. reinterpret cast to any char * type is permitted to allow reading the representation of any object – and one of the only cases where that keyword is useful, not a rampant generator of implementation-/undefined behaviour. But this isn’t considered a ‘normal’ conversion, so isn’t allowed by the (usually) very conservative static_cast.

    Jul 16, 2016 at 22:53

  • 2

    reinterpret_cast is pretty common when you are working with system software such as databases. Most cases you write your own page manager which has no idea about what is the data type stored in the page and just returns a void pointer. Its up to the higher levels to do a reinterpret cast and infer it as whatever they want.

    – Sohaib

    May 17, 2017 at 11:46

  • 1

    The first example is dangerous, in that it assumes good behavior on the part of the caller (to always pass a pointer to an actual EventData object and nothing else). Unfortunately I don’t think there’s any practical way to type-check a void pointer in any meaningful way. Ideally the argument would be strongly-typed. Just some observations; not a critique of the answer.

    Jan 29, 2019 at 15:29