0

Why and how can a const member function modify an object's mutable data member?

Member functions use the this pointer to modify the data members of an object. The this pointer of a const member function is a pointer to a constant, not a normal data member. So why is it always possible to modify the data members marked mutable of an object, and how does the compiler implement it?

Nelfeal
  • 12,593
  • 1
  • 20
  • 39
yxyc-137
  • 37
  • 2
  • "_The this pointer of a const member function is a pointer to a constant_": What do you imagine the difference to be between a `const` pointer and a non-`const` pointer from the point of view of the compiler? Also, how do you know that a `const` pointer actually points to a _constant_? You can make a `const` pointer to a non-constant object. – user17732522 May 28 '23 at 14:03
  • 2
    I don't understand the downvote. The OP has asked a perfectly legitimate question, IMO. – Paul Sanders May 28 '23 at 14:11
  • 1
    Does this answer your question? [Does the 'mutable' keyword have any purpose other than allowing the variable to be modified by a const function?](https://stackoverflow.com/questions/105014/does-the-mutable-keyword-have-any-purpose-other-than-allowing-the-variable-to) – BoP May 28 '23 at 14:41
  • @BoP I don't see how that question relates to this one. OP is asking about how the `mutable` keyword works, not about all its uses. – Nelfeal May 28 '23 at 16:05
  • 1
    When verbosely declared `mutable`, a member object will not inherit its owning objects const qualification; It will remain `mutable`. – Red.Wave May 29 '23 at 19:35

2 Answers2

7

The entire point of mutable member variables is that they can be modified via a const instance. So the fact that this is const has no relevance when modifying a mutable member variable--just as it has no relevance when reading a member variable.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • By default, the this pointer of a regular member function is a const pointer to a nonconstant, while the this pointer of a const member function is a const pointer to a constant. So I wonder if it's because a const member function that accesses the mutable data member accepts both a const pointer to a nonconstant (which accesses the mutable data member) and a const pointer to a constant (which accesses the general data member)?I want to know how it works – yxyc-137 May 28 '23 at 14:27
  • 2
    @yxyc-137 "_the this pointer of a const member function is a const pointer to a constant_": Where are you getting this from? A `const` pointer doesn't have to point to a constant object: `int i; const int* ptr = &i;`, `i` is not a constant object, but `ptr` is a `const` pointer to it. And indeed a `mutable` subobject is _never_ a constant object, even if the parent object is a constant object. Otherwise the `mutable` behavior wouldn't work. – user17732522 May 28 '23 at 14:28
  • 2
    @yxyc-137 No, the `this` pointer of a regular member function is not a const pointer. Many C++ textbooks incorrectly say what you're saying.(or you're saying what those books incorrectly say). The correct statement is the `this` pointer of a non-static non-const member function is `Class*` while the `this` pointer of a non-static const member function is `const X*`. – Jason May 28 '23 at 14:31
3

how does the compiler implement it?

Before asking how the compiler handles mutable, you should ask how the compiler handles const.

As the name implies, mutable is just another qualifier (or rather a storage class specifier) that interacts with how const is handled. It simply means that a mutable member variable can be modified, even if the containing object is declared const. It can also be modified through a const reference (or pointer) to the containing object. It does not directly relate to member functions.

Note that a mutable member variable cannot be modifier through a direct const reference (or pointer).

When looking at a mutating operation on a symbol, the compiler simply checks whether the symbol can be mutated in this context according to the rules above.

Example:

struct S {
    mutable int i;
};

int main() {
    S const object{0};
    object.i = 1; // ok because object.i is qualified `mutable`, even if object is `const`
    S const& ref = object;
    ref.i = 2; // ok because ref refers to an object that has a `mutable` member `i`

    int const& direct_ref = object.i;
    direct_ref = 3; // error because direct_ref directly refers to a `const` symbol
}
Nelfeal
  • 12,593
  • 1
  • 20
  • 39
  • Nice response to the question. It seems that OP doesn't understand what happens behind the compile process, and your linked question explains it. – Gorun May 28 '23 at 15:31