That's not undefined. That's exactly what const_cast is for. As long as the object itself is non-const then you can cast it away with const_cast and do the same things with it as a non-const pointer.
Do note that const_cast is usually considered a code smell and might indicate bad design.
As the standard says:
In the body of a non-static ([class.mfct]) member function, the
keyword this is a prvalue whose value is a pointer to the object for
which the function is called. The type of this in a member function of
a class X is X*. If the member function is declared const, the type of
this is const X*, if the member function is declared volatile, the
type of this is volatile X*, and if the member function is declared
const volatile, the type of this is const volatile X*.
The type of this is const X* in your case even though the object itself is non-const.
The standard says this about const_cast:
For two similar types T1 and T2, a prvalue of type T1 may be
explicitly converted to the type T2 using a const_cast. The
result of a const_cast refers to the original entity.
So, casting from const X* to X* is also legal.
Lastly, it says (albeit in a note):
[ Note: Depending on the type of the object, a write operation through
the pointer, lvalue or pointer to data member resulting from a
const_cast that casts away a const-qualifier may produce undefined
behavior ([dcl.type.cv]). — end note ]
And [dcl.type.cv] tells us:
Any attempt to modify ([expr.ass], [expr.post.incr], [expr.pre.incr])
a const object ([basic.type.qualifier]) during its lifetime
([basic.life]) results in undefined behavior.
Luckily, our this is pointing to a non-const object, so casting it and then modifying this object through the new non-const pointer doesn't trigger undefined behaviour.
Sorry Angew.