'mutable' variable mutable only by one of the const methods? - c++

today I have learned about the mutable keyword in C++ and would like to use it in my code.
I have a class with many const methods and one of them should be able to modify some of the object's variables (conserving the logical state of the object). However I don't want to let all the const methods to modify the variable, only the selected one. Is there any way of doing that? Maybe with const_cast?
(The code I am talking about is an implementation of the Union-Find structure. The Find operation does not change the logical state of the structure (it only searches for a root of a tree), but changes the physical state by doing so-called path compression)
Thanks!
EDIT: I have added an excerpt from the code I am referring to:
class UnionFind {
public:
void Union(int a, int b) {...}
int Find(int x) const {
// logically, this method is const
while(x != parents[x]) {
// path compression
// the next three lines modify parents and sizes,
// but the logical state of the object is not changed
sizes[parents[x]] -= sizes[x];
sizes[parents[parents[x]]] += sizes[x];
parents[x] = parents[parents[x]];
x = parents[x];
}
return x;
}
int someOtherMethodThatAccessesParents() const {
// this method does access parents, but read only.
// I would prefer if parents behaved like if it was
// not 'mutable' inside this method
...
}
private:
// these have to be mutable if I want the Find method
// to be marked const (as it should be)
// but making them mutable then does not enforce
// the physical non-mutability in other const methods :(
mutable std::vector<int> parents;
mutable std::vector<int> sizes;
};

On first glance this can't be achieved unless you use a nasty const_cast. But don't do that since the behaviour on attempting to modify a variable following a const_cast that was originally declared as const is undefined.
However, it might be feasible to achieve what you want using friendship since that can be controlled on a function by function basis whereas mutability, as you correctly point out, cannot be.
Put the variable you want to modify in a base class and mark it private. Perhaps provide a "getter" function to that member. That function would be const and would probably return a const reference to the member. Then make your function a friend of that base class. That function will be able to change the value of that private member.

If you can afford to use mutable, that is the right way to do it.
Still, it's possible to do what you are asking for. Normally this is done via the “fake this” idiom:
MyClass *mutableThis = const_cast<MyClass*>(this);
Then access your field normally through the new pointer. This is also the way to do it if you have to support some old compiler with no mutable support.
Note however that this is generally a dangerous practice, as it can easily lead you into the dreaded realm of undefined behavior. If the original object was actually declared const (as opposed to just being accessed via a const pointer/reference), you're asking for trouble.
In short: use mutable when you can, use fake this when you can't, but only when you know what you're doing.

Related

const_cast(this) performance hit

As far as I know , making constant functions in a class is useful for read/write compiler optimizations.
A constant function within a class means that the class members will remain constant during the execution of the function.
However, you can bypass this by const casting the implicit parameter (ofc this is a very bad practice).
My questions is as follows :
What pitfalls can the following code cause (especially in terms of performance unrelated to thread synchronization) ?
int myClass::getSomething() const
{
myClass* writableThis = const_cast<myClass*>(this);
writableThis->m_nMemberInt++;
...
return m_nSomeOtherUnchangedMember;
}
Another related question :
Is the behavior compiler/platform/os specific ?
I would also very much appreciate if someone could explain the magic under the hood when such a code is compiled/executed (I'm speculating that the CPU is making out-of-order optimizations based on the fact that the function is const , and not respecting this during actual execution should have some side effects).
EDIT :
Thank you for clarifying this for me. After further research all the received answers are correct but I can accept only one :).
Regarding the const qualifier being used solely for syntax corectness , I believe this answer is both right and wrong, the correct way to state this (imho) would be that it is used mostly for syntax corectness (in a very limited number of scenarios it can produce different / better code ). References : SO Related question , related article
The const_cast<T>(this) trick is potentially unsafe, because the user of your member function may run into undefined behavior without doing anything wrong on their side.
The problem is that casting away const-ness is allowed only when you start with a non-const object. If your object is constant, the function that casts away its const-ness and uses the resultant pointer to change object's state triggers undefined behavior:
struct Test {
int n;
Test() : n(0) {}
void potentiallyUndefinedBehavior() const {
Test *wrong = const_cast<Test*>(this);
wrong->n++;
}
};
int main() {
Test t1;
// This call is OK, because t1 is non-const
t1.potentiallyUndefinedBehavior();
const Test t2;
// This triggers undefined behavior, because t2 is const
t2.potentiallyUndefinedBehavior();
return 0;
}
The trick with const_cast<T>(this) has been invented for caching values inside member functions with const qualifier. However, it is no longer useful, because C++ added a special keyword for this sort of things: by marking a member mutable you make that member writable inside const-qualified methods:
struct Test {
mutable int n;
Test() : n(0) {}
void wellDefinedBehavior() const {
n++;
}
};
Now the const member function will not trigger undefined behavior regardless of the context.
The CPU doesn't know anything about const, which is a C++ keyword. By the time the compiler has transformed the C++ code to assembly, there's not much left of that.
Of course, there's a real possibility that the generated code is entirely different because of the const keyword. For instance, the const version of some operator[] may return a T object by value whereas the non-const version must return a T&. A CPU doesn't even know what function it's in, or even assume the existence of functions.
My answer is to use the storage class mutable for any thing which need to be modified in const methods.
It's built into the language, so there are several benefits. It's a tighter control for how const methods modify data members. Other developers will know these data members will change in const methods. If there are any compiler optimizations, the compiler will know to do the right thing.
class myClass {
private:
int m_nSomeOtherUnchangedMember;
mutable int m_nMemberInt;
…
public:
int getSomething() const;
…
};
int myClass::getSomething() const
{
m_nMemberInt++;
…
return m_nSomeOtherUnchangedMember;
}
As far as I know , making constant functions in a class is useful for read/write compiler optimizations.
No. We use const methods to enforce semantic guarantees, not to allow optimizations (with the possible exception of avoiding copies).
What pitfalls can the following code cause
Firstly, it can break program semantics.
For example, std::map nodes store std::pair<const Key, T>, because the Key shouldn't mutate after it has been inserted. If the key changes value, the map sorting invariant is incorrect, and subsequent find/insert/rebalance operations will misbehave.
If you call a const-qualified method on this const key, and that method changes the Key in a way that affects how it compares, then you've cunningly broken the map.
Secondly, it can kill your program. If you have a const object overlaid on a genuinely read-only address range, or you have a statically-initialized const object in the read-only initialized data segment, then writing to it will cause some kind of protection error
As other stated the const-correctness was designed as a help for the programmers and not an help for the optimizer. You should remember 4 things:
1. const references and const methods are not faster
2. const references and const methods are not faster
3. const references and const methods are not faster
4. const references and const methods are not faster
More specifically the optimizer simply completely ignores const-ness of references or of methods because const doesn't really mean in that context what you are thinking.
A const reference to an object doesn't mean that for example during the execution of a method the object will remain constant. Consider for example:
struct MyObject {
int x;
void foo() const {
printf("%i\n", x);
char *p = new char[10];
printf("%i\n", x);
delete[] p;
}
};
the compiler cannot assume that x member didn't mutate between the two calls to printf. The reason is that std::operator new global allocator could have been overloaded and the code could have regular non-const pointer to the instance. Therefore it's perfectly legal for the global allocator to change x during the execution of foo. The compiler cannot know this is not going to happen (the global allocator could be overloaded in another
compilation unit).
Calling any unknown code (i.e. basically any non-inlined function) can mutate any part of an object, being in a const method or not. The const method simply means that you cannot use this to mutate the object, not that the object is constant.
If const correctness is really an help for the programmers is another question on which I personally have a quite heretic point of view, but that's another story...

Is it a good practice to make a method which modifies data outside the class const?

I would like to ask a question about methods' const-correctness. Let me illustrate the situation.
class MyClass
{
public:
...
void DiscussedMethod() { otherClass->NonConstMethod(); }
private:
OtherClass *otherClass;
};
I have a class MyClass which keeps a pointer to OtherClass. In DiscussedMethod it calls OtherClass::NonConstMethod which modifies some visible data.
I would like to know, whether it would be a good practice to make the DiscussedMethod const (since it doesn't modify any member data)? Would it be a bad practice? Or is both fine?
What if the OtherClass kept a pointer to the MyClass and in NonConstMethod modified some of the MyClass' data (meaning that the MyClass member data would change during the DiscussedMethod call). Would it be a bad practice to make the DiscussedMethod const then?
As far as I've been able to find out, the const on a method is mostly a code documenting thing, so I would probably lean toward to not making the DiscussedMethod const, but I would like to hear your opinions.
EDIT: Some replies take the into account whether the object pointed to by otherClass is owned by the MyClass object. This is not the case in the scenario I'm working with. Lets say that both objects exist independently side by side (with the ability to modify each other). I think this analogy describes my situation quite well.
For example consider something like doubly-linked list, where each element is a class that keeps pointer to its neighbours and member variable color. And it has method MakeNeighboursRed which changes the color of its neighbours but doesn't affect the calling object's state itself. Should I consider making this method const?
And what if there was some possibility that MakeNeighboursRed would call neighbour's MakeNeighboursRed. So in the end the state of the object for which MakeNeighboursRed has been called originally would change as well.
And I would like to thank you all for your opinions :-)
If MyClass owns the OtherClass instance i wouldn't make DiscussedMethod constant.
The same goes for classes, managing resources. I.e. the standard containers do not return non const references or pointers to the managed memory using const functions, although it would be "possible" (since the actual pointer holding the resource is not modified).
Consider
class MyClass
{
public:
bool a() const { return otherClass->SomeMethod(); }
void b() const { otherClass->NonConstMethod(); }
private:
OtherClass *otherClass;
};
void foo (MyClass const &x)
{
cout << boolalpha << x.a() << endl;
x.b(); // possible if b is a const function
cout << boolalpha << x.a() << endl;
}
The foo could print two different values although an implementor of foo would probably expect that two function calls on a const object will have the same behaviour.
For clarification:
The following is invalid according to the standard since the const version of operator[] returns std::vector<T>::const_reference which is a constant reference to the value type.
std::vector<int> const a = { /* ... */ };
a[0] = 23; // impossible, the content is part of the state of a
It would be possible if there was only one signature of this function, namely referece operator[] (size_t i) const;, since the operation does not alter the internal pointers of the vector but the memory they point to.
But the memory, managed by the vector is considered to be part of the vectors state and thus modification is impossible through the const vector interface.
If the vector contains pointers, those pointer will still be unmodifiable through the public const vector interface, although the pointers stored in the vector may well be non const and it may well be possible to alter the memory they point to.
std::vector<int*> const b = { /* ... */ };
int x(2);
b[0] = &x; // impossible, b is const
*b[0] = x; // possible since value_type is int* not int const *
In OOP object should be fully described by its state, available through its interface. Thus, const methods should not alter object's state, if these changes might be observed through the interface.
A good example is a mutable mutex inside your class to guard some shared resources. It might be modified from const method, since it does not introduce any changes observable via class interface.
General rule of thumb is, that if you can make a member function const, you probably should. The reason for that is that it allows you to catch unintended behaviour and bug easier.
Another argument in favor would be that if you have this function as const you are allowed to call it on const object, so it isn't really a documentation thing.
Overall it depends what the other class is. It's not black and white...
If otherClass is a log object (for example) and you want to log the operation of the current object then it's perfectly fine calling it from a const function.
If the otherClass is a container that for design (or implementation) purposes is implemented as a separate object than effectively a const function modifies the object making this a very bad idea.
I hope this helps.
It's totaly incorrect to make DiscussedMethod const as it changes it's *this state. The only loophole to this is making non-logically-part-of-object's-state member data mutable so they can be changed in const functions. This would be things like a member that hold a count for "number of times function x() has been called". Any thing else is part of the object's state, and if a function changes it (at any level), that function isn't const.
I would like to know, whether it would be a good practice to make the DiscussedMethod const (since it doesn't modify any member data)?
otherClass is member data, and it (or rather, the object it points to) gets modified.
Consider the semantics should the pointer to otherClass be refactored to a fully-owned object... whether something is held as a pointer, reference, or object doesn't change the semantical ownership, IMO.

Is returning references of member variables bad practice?

The following is said to be better than having First() and Second() as public members. I believe this is nearly as bad.
// Example 17-3(b): Proper encapsulation, initially with inline accessors. Later
// in life, these might grow into nontrivial functions if needed; if not, then not.
template<class T, class U>
class Couple {
public:
Couple() : deleted_(false) { }
void MarkDeleted() { deleted_ = true; }
bool IsDeleted() { return deleted_; }
private:
T first_;
U second_;
bool deleted_;
T& First() { return first_; }
U& Second() { return second_; }
};
If you're giving a way to access a private variable outside of the class then what's the point? Shouldn't the functions be
T First(); void(or T) First(const T&)
There are several reasons why returning references (or pointers) to the internals of a class are bad. Starting with (what I consider to be) the most important:
Encapsulation is breached: you leak an implementation detail, which means that you can no longer alter your class internals as you wish. If you decided not to store first_ for example, but to compute it on the fly, how would you return a reference to it ? You cannot, thus you're stuck.
Invariant are no longer sustainable (in case of non-const reference): anybody may access and modify the attribute referred to at will, thus you cannot "monitor" its changes. It means that you cannot maintain an invariant of which this attribute is part. Essentially, your class is turning into a blob.
Lifetime issues spring up: it's easy to keep a reference or pointer to the attribute after the original object they belong to ceased to exist. This is of course undefined behavior. Most compilers will attempt to warn about keeping references to objects on the stack, for example, but I know of no compiler that managed to produce such warnings for references returned by functions or methods: you're on your own.
As such, it is usually better not to give away references or pointers to attributes. Not even const ones!
For small values, it is generally sufficient to pass them by copy (both in and out), especially now with move semantics (on the way in).
For larger values, it really depends on the situation, sometimes a Proxy might alleviate your troubles.
Finally, note that for some classes, having public members is not so bad. What would be the point of encapsulating the members of a pair ? When you find yourself writing a class that is no more than a collection of attributes (no invariant whatsoever), then instead of getting all OO on us and writing a getter/setter pair for each of them, consider making them public instead.
If template types T and U are big structures then return by value is costly. However you are correct that returning by reference is equivalent to giving access to a private variable. To solve both issues, make them const references:
const T& First() const { return first_; }
const U& Second() const { return second_; }
P.S. Also, it's a bad practice to keep variables uninitialized inside constructor, when there is no setter method. It seems that in the original code, First() and Second() are wrappers over first_ and second_ which were meant for read/write both.
The answer depends on what one is trying to do. Returning references are a convenient way to facilitate mutation of data structures. A good example is the stl map. It returns reference to the element i.e.
std::map<int,std::string> a;
a[1] = 1;
nothing to stop you from doing
auto & aref = a[1];
Is it necessarily a bad practice? I would not think so. I would say, if you can do without it do so. If it makes life more convenient and efficient use it and be aware of what you are doing.

RAII: Initializing data member in const method

In RAII, resources are not initialized until they are accessed. However, many access methods are declared constant. I need to call a mutable (non-const) function to initialize a data member.
Example: Loading from a data base
struct MyClass
{
int get_value(void) const;
private:
void load_from_database(void); // Loads the data member from database.
int m_value;
};
int
MyClass ::
get_value(void) const
{
static bool value_initialized(false);
if (!value_initialized)
{
// The compiler complains about this call because
// the method is non-const and called from a const
// method.
load_from_database();
}
return m_value;
}
My primitive solution is to declare the data member as mutable. I would rather not do this, because it suggests that other methods can change the member.
How would I cast the load_from_database() statement to get rid of the compiler errors?
This is not RAII. In RAII you would initialize it in the constructor, which would solve your problems.
So, what you are using here is Lazy. Be it lazy initialization or lazy computation.
If you don't use mutable, you are in for a world of hurt.
Of course you could use a const_cast, but what if someone does:
static const MyClass Examplar;
And the compiler decides it is a good candidate for Read-Only memory ? Well, in this case the effects of the const_cast are undefined. At best, nothing happens.
If you still wish to pursue the const_cast route, do it as R Samuel Klatchko do.
If you thought over and think there is likely a better alternative, you can decide to wrap your variable. If it was in class of its own, with only 3 methods: get, set and load_from_database, then you would not worry about it being mutable.
You are basically implementing a caching mechanism. Personally I think it's OK to mark cached data as mutable.
As Matthieu already pointed out, what you're trying to do here has little (if anything) to do with RAII. Likewise, I doubt that any combination of const and mutable is really going to help. const and mutable modify the type, and apply equally to all access to an object of that type.
What you seem to want is for a small amount of code to have write access, and anything else only read access to the value. Given the basic design of C++ (and most similar languages), the right way to do that is to move the variable into a class of its own, with the small amount of code that needs write access as part of (or possibly a friend of) that class. The rest of the world is given its read-only access via the class' interface (i.e., a member function that retrieves the value).
The (presumably stripped down) MyClass you've posted is pretty close to right -- you just need to use that by itself, instead of as part of a larger class with lots of other members. The main things to change would be 1) the name from MyClass to something like lazy_int, and 2) (at least by my preference) get_value() should probably be renamed to operator int(). Yes, m_value will probably need to be mutable, but this doesn't allow other code to write the value, simply because other code doesn't have access to the value itself at all.
Then you embed an object of that type into your larger class. The code in that outer class can treat it as an int (on a read-only basis) thanks to its operator int(), but can't write it, simply because the class doesn't give any way to do so.
[ LOOK MA! NO CASTS! :)) ]
struct DBValue
{
int get_value();
private:
void load_from_database();
int value;
};
struct MyClass
{
MyClass(): db_value(new DBValue()) {}
~MyClass() { delete db_value; }
int get_value() const;
private:
DBValue * const db_value;
};
int MyClass::get_value() const
{
return db_value->get_value(); // calls void load_from_database() if needed
}
The idea is to have a politically correct MyClass with const methods not mutating anything but calling both const and non-const methods of aggregated objects via const pointers.
Don't use const_cast here, or you're asking for trouble. Using mutable in this case shouldn't be a problem, but if the profiler didn't suggest otherwise then I think users would be less surprised to see an object that is expensive to construct than an accessor method that is expensive to call the first time.
If your method changes the state of the object (e.g. by changing the state of the underlying database), then the method should not be const. In that case you should have a separate, non-const load-method, that has to be called before the const getter can be called.
This method would require neither const_cast not mutable, and would make the potentially expensive operation explicit.

Member assignment in a const function

I have a class member myMember that is a myType pointer. I want to assign this member in a function that is declared as const. I'm doing as follows:
void func() const
{
...
const_cast<myType*>(myMember) = new myType();
...
}
Doing this works fine in VC++, but GCC gives an error with the message "lvalue required as left operand of assignment".
Making the member mutable allow me to simply remove the const_cast and assign the value. However, I'm not entirely sure that that comes with other side-effects.
Can I assign my member without having to make the member mutable? How? Are there any side-effects in making members mutable?
This scenario -- an encapsulated internal state change that does not impact external state (e.g. caching results) -- is exactly what the mutable keyword is for.
The code wont actually work in VC++ - you're not updating the value (or at least it shouldnt), hence the warning from GCC. Correct code is
const_cast<myType*&>(myMember) = new myType();
or [from other response, thanks :P]:
const_cast<ThisType*>(this)->myMember = new myType();
Making it mutable effectively means you get implicit const_casts in const member functions, which is generally what you should be steering towards when you find yourself doing loads of const_casts on this. There are no 'side-effects to using mutable' other than that.
As you can see from the vehement debates circling this question, willy-nilly usage of mutable and lots of const_casts can definitely be symptoms of bad smells in your code. From a conceptual point of view, casting away constness or using mutable can have much larger implications. In some cases, the correct thing to do may be to change the method to non-const, i.e., own up to the fact that it is modifying state.
It all depends on how much const-correctness matters in your context - you dont want to end up just sprinking mutable around like pixie dust to make stuff work, but mutable is intended for usage if the member isnt part of the observable state of the object. The most stringent view of const-correctness would hold that not a single bit of the object's state can be modified (e.g., this might be critical if you're instance is in ROM...) - in those cases you dont want any constness to be lost. In other cases, you might have some external state stored somewhere ouside of the object - e.g., a thread-specific cache which also needs to be considered when deciding if it is appropriate.
const_cast is nearly always a sign of design failure. In your example, either func() should not be const, or myMember should be mutable.
A caller of func() will expect her object not to change; but this means "not to change in a way she can notice"; this is, not to change its external state. If changing myMember does not change the object external state, that is what the mutable keyword is for; otherwise, func() should not be const, because you would be betraying your function guarantees.
Remember that mutable is not a mechanism to circunvent const-correctness; it is a mechanism to improve it.
class Class{
int value;
void func()const{
const_cast<Class*>(this)->value=123;
}
};
As Steve Gilham wrote, mutable is the correct (and short) answer to your question. I just want to give you a hint in a different direction.
Maybe it's possible in your szenario to make use of an (or more than one) interface?
Perhaps you can grok it from the following example:
class IRestrictedWriter // may change only some members
{
public:
virtual void func() = 0;
}
class MyClass : virtual public IRestrictedWriter
{
public:
virtual void func()
{
mValueToBeWrittenFromEverybody = 123;
}
void otherFunctionNotAccessibleViaIRestrictedWriter()
{
mOtherValue1 = 123;
mOtherValue2 = 345;
}
...
}
So, if you pass to some function an IRestrictedReader * instead of a const MyClass * it can call func and thus change mValueToBeWrittenFromEverybody whereas mOtherValue1 is kind of "const".
. I find mutable always a bit of a hack (but use it sometimes).