tags:

views:

1976

answers:

6

I can't find much information on const_cast. The only info I could find (on Stack Overflow) is:

The const_cast<>() is used to add/remove const(ness) (or volatile-ness) of a variable.

This makes me nervous. Could using a const_cast cause unexpected behavior? If so, what?

Alternatively, when is it okay to use const_cast?

+10  A: 

const_cast is safe only if you're casting a variable that was originally non-const. For example, if you have a function that takes a parameter of a const char *, and you pass in a modifiable char *, it's safe to const_cast that parameter back to a char * and modify it. However, if the original variable was in fact const, then using const_cast will result in undefined behavior.

void func(const char *param, size_t sz, bool modify)
{
    if(modify)
        strncpy(const_cast<char *>(param), sz, "new string");
    printf("param: %s\n", param);
}

...

char buffer[16];
const char *unmodifiable = "string constant";
func(buffer, sizeof(buffer), true);  // OK
func(unmodifiable, strlen(unmodifiable), false); // OK
func(unmodifiable, strlen(unmodifiable), true);  // UNDEFINED BEHAVIOR
Adam Rosenfield
+4  A: 

I find it hard to believe that that's the only information you could find about const_cast. Quoting from the second Google hit:

If you cast away the constness of an object that has been explicitly declared as const, and attempt to modify it, the results are undefined.

However, if you cast away the constness of an object that has not been explicitly declared as const, you can modify it safely.

Rob Kennedy
+1  A: 

You're destroying any chance at thread-safety, if you start modifying things that the compiler thought were const.

Matt Cruikshank
What? If you have immutable (const) objects, you can *trivially* share them amongst threads. The instant that a piece of your code casts away const-ness, you lose all of your thread safety! Why am I down-modded for this? *sigh*
Matt Cruikshank
Const is certainly a useful tool in making code thread-safe, but it gives no guarantees (except in the case of compile-time constants). Two examples: a const object may have mutable members, and having a const pointer to an object says nothing about whether the object itself could be changing.
James Hopkin
+1 for bringing the issue up, though :-)
James Hopkin
+2  A: 

What Adam says. Another example where const_cast can be helpful:

struct sample {
    T& getT() { 
        return const_cast<T&>(static_cast<const sample*>(this)->getT()); 
    }

    const T& getT() const { 
       /* possibly much code here */
       return t; 
    }

    T t;
};

We first add const to the type this points to, then we call the const version of getT, and then we remove const from the return type, which is valid since t must be non-const (otherwise, the non-const version of getT couldn't have been called). This can be very useful if you got a large function body and you want to avoid redundant code.

Johannes Schaub - litb
I would rather use static cast for the adding constness: static_cast<const sample*>(this).When I'm reading const_cast it means that the code is doing something potentially dangerous, so i try to avoid it's use when possible.
mfazekas
right, the first can be static_cast, or even be implicit_cast (of boost). i'll fix it using static cast. thanks
Johannes Schaub - litb
+3  A: 

I can think of two situations where const_cast is useful (there may be other valid cases).

One is when you have a const instance, reference, or pointer, and you want to pass a pointer or reference to an API that is not const-correct, but that you're CERTAIN won't modify the object. You can const_cast the pointer and pass it to the API, trusting that it won't really change anything. For example:

void log(char* text);   // Won't change text -- just const-incorrect

void my_func(const std::string& message)
{
    log(const_cast<char*>(&message.c_str()));
}

The other is if you're using an older compiler that doesn't implement 'mutable', and you want to create a class that is logically const but not bitwise const. You can const_cast 'this' within a const method and modify members of your class.

class MyClass
{
    char cached_data[10000]; // should be mutable
    bool cache_dirty;        // should also be mutable

  public:

    char getData(int index) const
    {
        if (cache_dirty)
        {
          MyClass* thisptr = const_cast<MyClass*>(this);
          update_cache(thisptr->cached_data);
        }
        return cached_data[index];
    }
};
Fred Larson
+2  A: 

The short answer is no, it's not safe.

The long answer is that if you know enough to use it, then it should be safe.

When you're casting, what you are essentially saying is, "I know something the compiler doesn't know." In the case of const_cast, what you are saying is, "Even though this method takes in a non-const reference or pointer, I know that it won't change the parameter I pass it."

So if you do actually know what you are claiming to know in using the cast, then it's fine to use it.

JohnMcG