TITLE: wheres and whys of const_cast (Newsgroups: comp.lang.c++.moderated, 1 Aug 99) RASPUTIN: Peter Rasputin >Could someone give me a C++ code example of const_cast and when you would >want to use it? NARAN: Siemel Naran It is almost always a bad idea. If the original object is const, then the result of the const_cast is undefined. But I know of 3 cases where const_cast is ok, and these are at the end. Example of why const_cast is dangerous: void f(const char * cc) { char * c=const_cast(cc); *c=toupper(*c); // may cause a memory access violation } int main() { const char c='c'; std::cout << c << '\n'; // prints "c" f(&c); std::cout << c << '\n'; // may print "c" or "C" } As main()::c is const, the compiler may evaluate it at compile time and store it in read-only memory (and the compiler can even eliminate storage for it if its address is not used). Hence the attempt to modify 'c' in f(const char *) would be a memory access violation or a segmentation fault. Let's suppose the compiler evaluates 'c' at run time and does not store it in read-only memory. Then the call to f(&c) does change 'c'. However, the compiler may replace the two lines std::cout << c << '\n'; std::cout << c << '\n'; with register register1=value of 'c'; std::cout << (char)register1 << '\n'; std::cout << (char)register1 << '\n'; As you've declared 'c' as "const char c=...", the compiler thinks that 'c' really is const and will never change. Hence it has pre-computed the value of 'c', stored it in a register (it can store 'c' in regular memory too if 'c' is big), and done const propogation to force the use of the stored/cached value of 'c'. Another example: typedef std::set Set; typedef Set::iterator Iter; int main() { Set set; set.insert(1); set.insert(2); set.insert(3); set.insert(4); // the ordering in the set is {1,2,3,4} as expected Iter i=set.find(2); if (i==set.end()) return 1; int& dangerous=const_cast(*i); dangerous=5; // this messes up the ordering of the set // the ordering in the set is {1,5,3,4} bad news! } Here are some legitimate uses of const_cast. 1. To add const qualifiers. Eg, int main(int argc, char * * argv_) { char *const * argv=argv_; // ok: can add 1st level const char const *const * argv=argv_; // error: can't add 2nd level const char const *const * argv=const_cast(argv_); // ok } 2. Change one of many objects. void f() { string s1="Hello"; string s2="World"; min(s1,s2)+="Thing"; } But the declaration of std::min is as follows const T& min(const T& lhs, const T& rhs); Alas, we have to do it like this: const_cast(min(s1,s2))+="Thing"; This use of const_cast is perfectly legitimate because we know that a non-const version of the object is available. In general, if we create a non-const object in scope S (in the above, S is f()::), then it is always ok to use const_cast on this object in scope S. 3. Some old functions take "T *" parameters even though they don't modify the pointed to object or pointed to array. So one could use const_cast to pass pointers to these functions. (Private correspondence) TRIBBLE: David R Tribble There is another, albeit controversial, use of const_cast. This is when you wish to delete an object through a pointer-to-const: const Type *p = ...; ... delete const_cast(p); p = NULL; ... The standard explicitly allows you to delete a const object without needing a cast: delete p; // legitimate But some programmers feel that this opens up a hole in the type safety mechanisms of C++, since the compiler is not obliged to give you a warning that 'p' points to a const object, which might not be what you intended. Therefore, some programmers feel that the intention is clearer if an explicit const_cast is used.