3

See the following:

struct A
{
    std::string* get() const
    {
        //return const_cast<std::string*>(&m_pObj);
        return &const_cast<A*>(this)->m_pObj;
    }

    std::string m_pObj;
};

Is dereferencing const_cast of this UB? Is there any time dereferencing the result from const_casting the constness of a pointer away doesn't invoke UB?

(I know the above example is bad practice, bad design, and could be solved with mutable - that's not the point)

David
  • 27,652
  • 18
  • 89
  • 138

4 Answers4

9

Is dereferencing const_cast of this UB? Is there any time dereferencing the result from const_casting the constness of a pointer away doesn't invoke UB?

Not always, only if the object is const (the A instance is const A x;) and the dereference is used to modify the data. If it is only used to read it will not be undefined behavior, if the object is not const, (maybe not at all, maybe a const-reference to a non-const object) it won't be UB either.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
3

No, it is only UB if the referenced object has been declared as const originally and you subsequently modify the data obtained by the cast (§5.2.11/7 and §7.1.6.1/4). The following is legal:

A a;
a.get()->clear();

while this isn’t (and is consequently UB):

A const a;
a.get()->clear();
Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • 4
    As long as the dereference is not used to *modify* the object, there is no UB. That is: `A const a; std::cout << *a.get();` is fine, but `a.get()->clear();` is not. – David Rodríguez - dribeas Jun 15 '12 at 15:46
  • @David yes; see update. Oh, and I prefer your example (`->clear()`) to mine (dereference + modify `[0]`) so I’ve stolen it, I hope you don’t mind. – Konrad Rudolph Jun 15 '12 at 15:48
1

No. To wit:

5.2.2 Function call

5 [ Note: a function can change the values of its non-const parameters, but these changes cannot affect the values of the arguments except where a parameter is of a reference type (8.3.2); if the reference is to a const-qualified type, const_cast is required to be used to cast away the constness in order to modify the argument’s value. Where a parameter is of const reference type a temporary object is introduced if needed (7.1.6, 2.14, 2.14.5, 8.3.4, 12.2). In addition, it is possible to modify the values of nonconstant objects through pointer parameters. —end note ]

However,

5.2.11 Const cast

12 [ Note: some conversions which involve only changes in cv-qualification cannot be done using const_cast. For instance, conversions between pointers to functions are not covered because such conversions lead to values whose use causes undefined behavior. For the same reasons, conversions between pointers to member functions, and in particular, the conversion from a pointer to a const member function to a pointer to a non-const member function, are not covered. —end note ]

Community
  • 1
  • 1
dirkgently
  • 108,024
  • 16
  • 131
  • 187
0

A compiler is free to store a const value in read-only memory, it is free to make assumptions that it will never change when optimising the program. If you cast away the constness, you are breaking the contract with the compiler so technically anything can happen.

Realistically, it is pretty rare for a compiler to do something that will be broken by const_cast-ing, but in theory it is possible.

Michael J
  • 7,631
  • 2
  • 24
  • 30
  • Which of the earlier answers isn't correct? They all said that attempting to modify a const object is undefined behavior. Casting away const is perfectly legal, always, and modifying the object through the results of the cast is also legal (and well defined) if the object itself isn't const. – James Kanze Jun 15 '12 at 16:02
  • You are right (I've removed the statement). I read them a bit too quickly. All began with "no" and or "not always", which seemed wrong, but on better reading I see they qualified it adequately. Apologies. – Michael J Jun 15 '12 at 16:08