14

Since with help of const_cast anyone can modify my declared constant object - what use is the const qualifier?

I mean how can someone ensure that what he declared const is not going to be modified anyway?

Ofek Shilon
  • 14,734
  • 5
  • 67
  • 101
mac mohan
  • 165
  • 1
  • 9
  • 3
    It's the same as with `reinterpret_cast`, `union`, `memcpy` and many others: There's always a way to circumvent safety mechanisms in C++, mostly invoking undefined behaviour. That you can break them doesn't mean that these mechanisms don't provide benefit. – dyp Sep 17 '13 at 05:50
  • 1
    "what he has declared as a const is not going to modified anyways??" By convention, a `const`-qualified object won't change its *observable behaviour*. It doesn't mean that it's bits won't be modified. – dyp Sep 17 '13 at 05:58
  • Lazy evaluation (http://stackoverflow.com/questions/881119/dealing-with-lazy-computation-in-c-classes), but probably using mutable is better than e.g. const_cast<...>(this). – user2672165 Sep 17 '13 at 06:13
  • possible duplicate : http://stackoverflow.com/questions/2673508/correct-usages-of-const-cast – IlanS Sep 17 '13 at 10:07

4 Answers4

14

You are right, uses of const_cast often indicates a design flaw, or an API that is out of your control.

However, there is an exception, it's useful in the context of overloaded functions. I'm quoting an example from the book C++ Primer:

// return a reference to the shorter of two strings
const string &shorterString(const string &s1, const string &s2)
{
    return s1.size() <= s2.size() ? s1 : s2;
}

This function takes and returns references to const string. We can call the function on a pair of non-const string arguments, but we’ll get a reference to a const string as the result. We might want to have a version of shorterString that, when given non-const arguments, would yield a plain reference. We can write this version of our function using a const_cast:

string &shorterString(string &s1, string &s2)
{
    auto &r = shorterString(const_cast<const string&>(s1),
                            const_cast<const string&>(s2));
    return const_cast<string&>(r);
}

This version calls the const version of shorterString by casting its arguments to references to const. That function returns a reference to a const string, which we know is bound to one of our original, non-const arguments. Therefore, we know it is safe to cast that string back to a plain string& in the return.

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
8

Nobody can modify your constant object, with const_cast or without it. const_cast does not allow one to modify constant objects.

When it comes to removing constness, the purpose of const_cast is to allow you remove constness from an access path (pointer or reference) that leads to a non-constant object.

For example

int i = 5;
const int *p = &i;

*const_cast<int *>(p) = 10;
assert(i == 10);

In the above code const_cast is used to gain modifying access to object i through pointer p. Object i is not constant itself, so there's nothing wrong with that modification.

That's the purpose of const_cast. It can also be used for the opposite purpose: adding constness to pointer or reference type. But "modifying constant objects" is not something you can do with const_cast. Constant objects are not modifiable.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • 1
    Is that right? The code `const int x = 42; int *px = const_cast(&x); *px = 3;` appears to modify the memory. – paxdiablo Sep 30 '20 at 06:17
7

const_cast is only safe if you are adding const to an originally non-const variable. Trying to remove the const status from an originally-const object, and then perform the write operation on it will result in undefined behavior.

This question is related.

Also, the msdn page says (emphasis mine):

A pointer to any object type or a pointer to a data member can be explicitly converted to a type that is identical except for the const, volatile, and __unaligned qualifiers. For pointers and references, the result will refer to the original object. For pointers to data members, the result will refer to the same member as the original (uncast) pointer to data member. Depending on the type of the referenced object, a write operation through the resulting pointer, reference, or pointer to data member might produce undefined behavior. You cannot use the const_cast operator to directly override a constant variable's constant status.

Community
  • 1
  • 1
SingerOfTheFall
  • 29,228
  • 8
  • 68
  • 105
  • I thought that non-const to const was an upcast and didn't need explicit cast? – John Dvorak Sep 17 '13 at 05:50
  • @JanDvorak For some pointer conversions, it's required, such as from `int**` to `int const**`. – dyp Sep 17 '13 at 05:52
  • 1
    Another point: You can safely remove the `const` from any object that hasn't been declared `const`. `int i; int const* p = &i; int* pp = const_cast(p); *pp = 42;` is safe. – dyp Sep 17 '13 at 05:53
  • @DyP, that's why it says "depending on the type of the referenced object" ;) – SingerOfTheFall Sep 17 '13 at 05:58
  • @SingerOfTheFall I was referring to your own text before that quote "If you will try to remove the const with it, you will get UB." This isn't complete/precise in two ways: 1) UB will only occur if you do a write-operation on that object 2) UB will only occur if the object itself is const (has been defined as const) – dyp Sep 17 '13 at 06:01
  • @DyP, I've tried to rephrase it to make it more clear, thanks. – SingerOfTheFall Sep 17 '13 at 06:05
  • @DyP I can't see why it should be required – John Dvorak Sep 17 '13 at 06:11
  • @JanDvorak [See the C++ FAQ](http://www.parashift.com/c++-faq/constptrptr-conversion.html) – dyp Sep 17 '13 at 06:20
3

One possible use for const_cast to cast away constness, is to call C functions that don't use const arguments but still doesn't modify their arguments, or only modifies their local copies.

Casting away the const part and then modify the data will most certainly lead to undefined behavior otherwise.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621