Does the 'Mutable' Keyword Have Any Purpose Other Than Allowing the Variable to Be Modified by a Const Function

Does the 'mutable' keyword have any purpose other than allowing the variable to be modified by a const function?

It allows the differentiation of bitwise const and logical const. Logical const is when an object doesn't change in a way that is visible through the public interface, like your locking example. Another example would be a class that computes a value the first time it is requested, and caches the result.

Since c++11 mutable can be used on a lambda to denote that things captured by value are modifiable (they aren't by default):

int x = 0;
auto f1 = [=]() mutable {x = 42;}; // OK
auto f2 = [=]() {x = 42;}; // Error: a by-value capture cannot be modified in a non-mutable lambda

Why is Mutable keyword used

It allows you to write (i.e. "mutate") to the rno member through a student member function even if used with a const object of type student.

class A {
mutable int x;
int y;

public:
void f1() {
// "this" has type `A*`
x = 1; // okay
y = 1; // okay
}
void f2() const {
// "this" has type `A const*`
x = 1; // okay
y = 1; // illegal, because f2 is const
}
};

Mutable variable changed by a non-const member function

It's legal to modify mutables in const functions and of course it's legal to modify mutables in non-const functions (as each non-const member-variable). mutable keyword allows modify variable in const functions, but doesn't give any restrictions on modifying in non-const functions.

Const Object, Const Member Function and Mutable Variable in C++

Does [Section 9.3.2, Paragraph 3 of] make sense if the member function does not modify anything? Or if the member function modifies a mutable variable?

Yes, it does. The caller of the function cannot in general know whether the function modifies any non mutable member. It knows whether the function is const or not, so the compiler can only make a decision based on that.

A non const function could modify the non mutable state, so you obviously may not call it on a const object. Whether the non const function does modify the state is irrelevant since it is an implementation detail that is not available when deciding if the call is allowed. In other words, constness is part of the interface of the function, while the implementation of the function is not part of the interface. The interface of the function is fully specified by its declaration.

An example:

struct C {
mutable int a;
int b;
void do_something();
};

const C c;
c.do_something();

Does it make sense to allow the call do_something? Does the fact that do_something might not modify b affect that? How could we assume that do_something does not modify b?

The answers are: It wouldn't make sense. It does not have an effect. There is no way we could make such assumption.

Writing a non const member function that doesn't modify any non mutable state - at least potentially or allow such modification indirectly by returning a non const reference / pointer to this - makes little sense, although the standard does permit doing so.

So in the end, I need to write const to be able to modify something, which should be the opposite purpose of const.

That might seem oxymoronic, but that is because it is an oversimplification. You need to write const to be able to modify the mutable state of a const object. The const that you write declares that you do not modify any non mutable state, and that declaration gives the permission to call it on const objects.

Your commented-out non-const function is still correct to use with non-const objects.

Is it correct to specify class-member mutex 'mutable' for the purpose of much-more 'const' member functions?

Not only is this correct, but also standard practice. A member mutex is described as "non observably non-const", which means it behaves as a constant to a "user" observer.

Herb Sutter has popularized the M&M rule:

For a member variable, mutable and mutex (or atomic) go together.

The rule's section related to your question states:

For a member variable, mutex (or similar synchronization type) implies mutable: A member variable that is itself of a synchronization type, such as a mutex or a condition variable, naturally wants to be mutable, because you will want to use it in a non-const way (e.g., take a std::lock_guard<mutex>) inside concurrent const member functions.

The linked article has many code examples and further elaboration, should you want to dive deeper.

Impact of a mutable member on a complete const object and UB

dcl.stc#9 says:

[Note 4: The mutable specifier on a class data member nullifies a const specifier applied to the containing class object and permits modification of the mutable class member even though the rest of the object is const ([basic.type.qualifier], [dcl.type.cv]).
— end note]

(emphasis mine)

This means that a modification of only the mutable class member is permitted and if we try to modify any other non-mutable data members of such a const object the result will still be undefined as "the rest of the object is const".

In your example this means that only the mi mutable data member is permitted to be modified for a const A object and if we try to modify i the result will be undefined.

Detecting memory leaks in C programs?

As suggested, there already exist excellent tools like Valgrind to do this.

Further:

I would like to do this without any external utilities for practice

This is interesting and I am sure would be fulfilling,

You can use macro trick to detect such memory usage and leak errors, in fact write your own neat leak detector. You should be able to do this as long as you have a single allocation and deallocation function in your project.

#define malloc(X) my_malloc( X, __FILE__, __LINE__, __FUNCTION__)

void* my_malloc(size_t size, const char *file, int line, const char *func)
{

void *p = malloc(size);
printf ("Allocated = %s, %i, %s, %p[%li]\n", file, line, func, p, size);

/*Link List functionality goes in here*/

return p;
}

You maintain a Linked List of addresses being allocated with the file and line number from where there allocated. You update the link list with entries in your malloc.

Similar to above you can write an implementation for free, wherein you check the address entries being asked to be freed against your linked list. If there is no matching entry its a usage error and you can flag it so.

At the end of your program you print or write the contents of your linked list to an logfile. If there are no leaks your linked list should have no entries but if there are some leaks then the logfile gives you exact location of where the memory was allocated.

Note that in using this macro trick, you lose the type checking which functions offer but it's a neat little trick I use a lot of times.

Hope this helps and All the Best :)



Related Topics



Leave a reply



Submit