8

I just came across this code fragment, but I do not understand how it compiles:

class temp {
    int value1; 
    mutable int value2;
public:
    void fun(int val) const
    {
        ((temp*) this)->value1 = 10;
        value2 = 10;
    }
};

What is the meaning of this line

((temp*) this)->value1 = 10;

value1 is getting assigned to 10, without any error. But value1 is not mutable. How does this compile?

3
  • That cast is to make an otherwise-const temp * a temp *. It is also outright hideous.
    – WhozCraig
    Commented Aug 26, 2015 at 18:23
  • 16
    It means whoever wrote this code shouldn't be allowed to write code anymore.
    – Praetorian
    Commented Aug 26, 2015 at 18:24
  • Technically (potentially) Undefined Behaviour. If you had const temp a; a.fun(4);, then the line you quotes would be modifying an actually const variable. The assignment to value2 is not because value2 has been declared as mutable (and doesn't need nasty C-style or const_cast to make it work...) Commented Aug 26, 2015 at 21:40

3 Answers 3

11

When a member variable does not have the mutable qualifier, you cannot modify it when an object is const.

When a member variable has the mutable qualifier, you can modify it even when an object is const.

Simple example:

struct Foo
{
   int var1;
   mutable int var2;
};

const Foo f{};
f.var1 = 10; // Not OK
f.var2 = 20; // OK

When you have:

void fun(int val) const
{
    ((temp*) this)->value1 = 10;
    value2 = 10;
}

you are bypassing the const-ness of the object and changing it in a way that you are not supposed to. This is subject to undefined behavior.

As far as the compiler is concerned, that code is equivalent to:

void fun(int val) const
{
    temp* ptr = (temp*)this

    // The compiler does not know how you got ptr.
    // It is able to modify value1 through ptr since ptr
    // points to a non-const object.
    ptr->value1 = 10;

    value2 = 10;
}
6
  • const Foo f{}; you ment const Foo f();
    – MaxDevelop
    Commented Aug 26, 2015 at 18:34
  • 3
    @Saif Actually he definitely meant {} as if he'd used () it'd be a function declaration...
    – Barry
    Commented Aug 26, 2015 at 18:35
  • 1
    @Saif, const Foo f{}; constructs a const- object. const Foo f(); would declare a function f that takes no arguments and returns a const Foo.
    – R Sahu
    Commented Aug 26, 2015 at 18:40
  • @R Sahu: Actually fun is a const member function, value1 should not change unless it is made mutable or use const_cast. How is it possible to change value in const fun.
    – Phani
    Commented Aug 26, 2015 at 18:59
  • 1
    @Phani, by using an explicit cast, like ((temp*) this), you are bypassing the const-ness of the object.
    – R Sahu
    Commented Aug 26, 2015 at 19:01
2

The line

((temp*) this)->value1 = 10;

is said to be "casting away const-ness". It basically tells the compiler: Take the this pointer (which has the type temp const* because we are in a const member function of temp), and pretend it were of type temp* (the subexpression (temp*)this). Then it instructs the compiler to dereference this pointer of type temp* to modify one of its members.

Casting away const-ness was how mutable data members were implemented before C++ offered the mutable keyword.

As you might have guessed, this is bad practice. It is bad practice, because it could just as well have been expressed with the mutable modifier. And it is bad practice because it uses the big gun of a C-style cast where a C++ const_cast<> would have sufficed.

0
1

The best way to learn is to start making it a trivial case and see how it goes.

a) if you comment out (*temp) and make it something like this->value1 = 10;

error: assignment of data-member ‘temp::value1’ in read-only structure

or

b) if you comment out mutable keyword, you'll get the same error

error: assignment of data-member ‘temp::value2’ in read-only structure

and if you read above R Sahu provided the right answer about mutable keyword.

If you are confused why can't we modify value with the normal way, remember the function is const and const is a contract that promises we are not supposed to modify or assign any values here (but mutable). so it is basically showing two techniques or hacks to break promise :-)

Not the answer you're looking for? Browse other questions tagged or ask your own question.