c++constantsundefined-behaviorconst-cast

Is it allowed to cast away const on a const-defined object as long as it is not actually modified?


Is the following allowed:

const int const_array[] = { 42 };

int maybe_inc(bool write, int* array) {
  if (write) array[0]++;
  return array[0];
}

int main() {
  return maybe_inc(false, const_cast<int *>(const_array));
}

In particular, is it OK to cast-away the constness of const_array, which was defined as const, as long as the object is not actually modified, as in the example?


Solution

  • Yes. This is entirely legal. (It is dangerous, but it is legal.) If you (attempt to) modify an object declared const, then the behaviour is undefined.

    From n4659 (which is the last draft of C++17), section 10.1.7.1 [dcl.type.cv] para 4:

    Except that any class member declared mutable (10.1.1) can be modified, any attempt to modify a const object during its lifetime (6.8) results in undefined behavior

    My emphasis. That is from C++17, but this has been true of all versions of C++.

    If you look at the section on const_cast there is a note that

    [ 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-qualifier76 may produce undefined behavior (10.1.7.1). — end note ]

    Notes are not normative, but this strongly implies that obtaining a non-const reference or pointer to a const object is legal. It is the write that is not allowed.


    New references for C++20:

    From N4680 (which is the last draft of C++20), section 9.2.8.1 [dcl.type.cv] para 4:

    Any attempt to modify (7.6.19, 7.6.1.5, 7.6.2.2) a const object (6.8.3) during its lifetime (6.7.3) results in undefined behavior.

    If you look at the section on const_cast, section 7.6.1.10 [expr.const.cast] para 6 linking to above statement:

    [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 (9.2.8.1).]