Const_cast 安全吗?

我找不到关于 const_cast的太多信息。我能找到的(关于堆栈溢出)的唯一信息是:

const_cast<>()用于添加/删除变量的常数(ness)(或易失性)。

这让我很紧张。使用 const_cast会导致意想不到的行为吗? 如果会,是什么?

或者,什么时候可以使用 const_cast

51087 次浏览

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

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.

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

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.

I can think of two situations where const_cast is safe and 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];
}
};

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.