58

I have a private variable in my Student class defined as:

const int studentNumnber;

I am trying to write a copy constructor for the Student and I need to cast away the constness to do this. Unfortunately, I don't understand how to use std::const_cast.

This is what I am trying to do in my copy constructor:

    Student(const Student & s) 
        : Person(p.getName(), p.getEmailAddress(), p.getBirthDate()), school(0), studentNumber(0) {
        school = new char[strlen(s.school) + 1];
        strcpy_s(school, strlen(s.school) + 1, s.school);
        const_cast<int*>(this)->studentNumber = s.studentNumber;
        //studentNumber = s.studentNumber);
    }

That doesn't work... I am unsure of the syntax.

Ardent Coder
  • 3,777
  • 9
  • 27
  • 53
Sarah
  • 2,713
  • 13
  • 31
  • 45
  • Does this answer your question? [Is it allowed to cast away const on a const-defined object as long as it is not actually modified?](https://stackoverflow.com/questions/54504247/is-it-allowed-to-cast-away-const-on-a-const-defined-object-as-long-as-it-is-not) – Thomas Weller Mar 09 '23 at 17:33

2 Answers2

138

You are not allowed to const_cast and then modify variables that are actually const. This results in undefined behavior. const_cast is used to remove the const-ness from references and pointers that ultimately refer to something that is not const.

So, this is allowed:

int i = 0;
const int& ref = i;
const int* ptr = &i;

const_cast<int&>(ref) = 3;
*const_cast<int*>(ptr) = 3;

It's allowed because i, the object being assigned to, is not const. The below is not allowed:

const int i = 0;
const int& ref = i;
const int* ptr = &i;

const_cast<int&>(ref) = 3;
*const_cast<int*>(ptr) = 3;

because here i is const and you are modifying it by assigning it a new value. The code will compile, but its behavior is undefined (which can mean anything from "it works just fine" to "the program will crash".)

You should initialize constant data members in the constructor's initializers instead of assigning them in the body of constructors:

Student(const Student & s) 
    : Person(p.getName(), p.getEmailAddress(), p.getBirthDate()),
      school(0),
      studentNumber(s.studentNumber)
{
    // ...
}
timrau
  • 22,578
  • 4
  • 51
  • 64
  • 2
    "You should initialize data members..." not just const data – Caleth Jan 24 '19 at 11:26
  • What is the part that is not allowed about casting away constness from objects that are _actually_ (defined) const? The _cast itself_, or the subsequent modification? – BeeOnRope Feb 03 '19 at 15:14
  • 27
    _"You are not allowed to const_cast variables that are actually const"_ This is not true. Writing to such a variable has undefined behaviour, but the cast itself is 100% legal (but a bad idea because it creates the possibility to reach said UB!) – Lightness Races in Orbit Feb 03 '19 at 15:28
  • 7
    See https://stackoverflow.com/a/54504302/9204 for confirmation that this answer is wrong. – Alexey Romanov Sep 20 '19 at 10:37
  • 4
    what's the point of language having a `const_cast` if it can result in undefined behavior? makes no sense. – metablaster Oct 05 '19 at 16:20
  • Then why this works? `const char* s = "abc"; char*p = const_cast(s);` the `s` points to a constant, and yet `const_cast` didn't complain. – daparic Aug 13 '20 at 13:04
  • @metablaster, See "Lightness Races in Orbit" and Alexey Romanov's comment – user1032677 Aug 28 '20 at 04:19
  • @timrau: would you mind modifying the beginning of your answer from `You are not allowed to const_cast variables [...]` to `You are not allowed to const_cast and then modify variables [...]` ? I think this was your intention. And I think that's what's actually correct according to the N4860 draft, "expr.const.cast" chapter 7.6.1.10 (6). The note says "[...] a write operation through [...]". I can do the edit for you, if you like. Just drop me a comment. – Thomas Weller Mar 09 '23 at 18:26
  • @timrau: see also https://stackoverflow.com/a/54504302/480982 – Thomas Weller Mar 09 '23 at 18:42
-8

In your code you are trying cast this pointer instead of variable. You can try the following:

Student(const Student & s)
    : Person(p.getName(), p.getEmailAddress(), p.getBirthDate()), school(0), studentNumber(0) {
    school = new char[strlen(s.school) + 1];
    strcpy_s(school, strlen(s.school) + 1, s.school);
    *const_cast<int*>(&studentNumber) = s.studentNumber;
}