0

Why can a non-static const member be assigned using const_cast, and when would this be useful?

In the following code, both A and B classes compile and work fine. However, for B, its const member s is not initialized using an initializer list in the constructor, but by removing the const with const_cast and passing it a value by reference. It can also be written as (string&)s = _s;

I don't often see a const_cast on the left side of an assignment, but this one seems to work fine. What are the pros and cons of B's constructor?

#include <cstdlib>
#include <iostream>
#include <string>
using namespace std;

class A {
public:
    A(const string& _s) : s(_s) {}
    void display() {cout << s << endl;}
private:
    const string s;
};

class B {
public:
    B(const string& _s) {
        const_cast<string&>(s) = _s;
    }
    void display() {cout << s << endl;}
private:
    const string s;
};

int main() {
    A a("abc");
    a.display();
    B b("def");
    b.display();
    return EXIT_SUCCESS;
}

Output:

abc
def
andreipb
  • 79
  • 8
  • 2
    The "cons" of `B::B` is that is has an unnecessary `const_cast`. It has nothing in its "pros" list. – François Andrieux Mar 23 '20 at 16:46
  • 1
    Using `const_cast` to assign to a `const` object is UB. – super Mar 23 '20 at 16:51
  • 1
    _Why can (bad thing) be done in C++?_ Because C++ is not a nanny language, and provides you enough rope to shoot yourself in the foot. When the programmer uses a cast, they're telling the compiler "trust me, I know what I'm doing" and the compiler trusts them even if they don't know what they're doing. – Eljay Mar 23 '20 at 17:04
  • 1
    Only use `const_cast` if you know for sure that the object the `const` reference is referencing is not declared `const`. Otherwise you will cause undefined behavior sooner or later when trying to modify a `const` object. And even for these cases, there are usually alternatives that don't require the cast. – walnut Mar 23 '20 at 17:09

1 Answers1

3

Why can a non-static const member be assigned using const_cast, and when would this be useful?

Depends on what you mean by "can".

The program is well-formed because you modify a non-const lvalue.

The behaviour of the program is undefined because you modify a const object.

and when would this be useful?

Modifying a const object can never be useful.

Casting away const from a reference is sometimes, although rarely, useful which is why const_cast exists. But it is only useful when you have a const reference to a non-const object.

What are the pros ... of B's constructor?

None.

What are the ... cons of B's constructor?

The behaviour of the program is undefined if B's constructor is called.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • Thank you. Does the answer also hold if instead of `const_cast(s) = _s;` I write `(string&) s = _s;`? I believe that the 2nd variant is in reality converted to the 1st one by the compiler. – andreipb Mar 24 '20 at 08:33
  • 1
    Yes. That is equivalent. Avoid using the latter in all cases. Only cast away constness with const cast. – eerorika Mar 24 '20 at 10:43