Is it safe to remove const via const_cast and call a non-const function that does not modify the resulting object?

I know that disabling const -ness should be done with caution, and any attempt to remove const -ness from the original const object, followed by a change in the object, will lead to undefined behavior. What if we want to remove const -ness so that we can call the non-const function, which does not modify the object? I know that we should actually mention such a const function, but suppose I use "bad" code that does not have an available version of const .

So to summarize, is the code below “safe”? I assume that until you finish modifying the object, you're fine, but I'm not 100% sure.

 #include <iostream> struct Foo { void f() // doesn't modify the instance, although is not marked const { std::cout << "Foo::f()" << std::endl; } }; int main() { const Foo foo; const_cast<Foo&>(foo).f(); // is this safe? } 
+6
source share
3 answers

Undefined behavior with respect to const_cast is defined by the C ++ 11 standard §3.8 / 9 (§3.8 - "Object lifetime"):

" . Creating a new object in the storage location where the const object is located with static, streaming or automatic expiration dates or in the storage location in which such a const object is used is occupied before its service life has ended in undefined results.

and §7.1.6.1 / 4 (§7.1.6.1 - “cv-qualifiers”)

" Except that any member of the class declared mutable (7.1.1) can be modified, any attempt to change a const object during its lifetime (3.8) leads to undefined behavior.

In other words, you get UB if you modify the object initially const , otherwise 1 not.

const_cast itself const_cast not introduce UB.


In addition, in §5.2.11 / 7 there is a non-normative note in which, depending on the type, an entry through a pointer or a link obtained from a const_cast can be undefined.

This non-normative note is so dumb that it has its own non-normative footnote, which explains that " const_cast not limited to transformations that discard const -qualifier.".

However, with this clarification, I can not imagine a single case where the record can be clearly defined or does not depend on the type, i.e. I do not understand the meaning of this note. The other two answers here focus on the word “write” in this note and that it is necessary to get to UB-earth through § 3.8 / 9, yes. For me, a rather suspicious aspect is “depending on the type,” which seems to be a significant part of this post.


1) Except when UB rules about other events not related to t220 come into play, for example. nulling a pointer that is later dereferenced in a context other than typeid -expression.

+3
source

This specific example is safe (has well-defined behavior) because there is no record for an object declared const .

+6
source

We have this in [dcl.type.cv]:

Except that any member of the class declared mutable (7.1.1) can be modified, any attempt to modify the const object during its lifetime (3.8) leads to undefined behavior.

And there is a note (non-normative) in [expr.const.cast] that says:

[Note. Depending on the type of object, a write operation through a pointer, lvalue, or a pointer to a data element that is the result of a const_cast that discards the const specifier can cause undefined behavior (7.1.6.1). -end note]

Attempting to modify an object or write operation after const_cast [may] will result in undefined behavior. Here we do not have a write operation.

+6
source

Source: https://habr.com/ru/post/986014/


All Articles