const_cast(this) performance hit - c++

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...

Related

Violating const correctness: What problems should I expect realistically?

I want to use a function parser library where the member function FunctionParser::Eval() is non-const, because it writes an error code to a member variable. I would like to integrate this function parser into a codebase, where this function would get called through a const member function of a class holding that function parser, thus violating const correctness.
This const member function is part of an interface, where the constness makes semantic sense. I could change that interface, so that remains an option.
As a test, I used const_cast to execute the code violating const correctness, which did not cause any errors or failed unit tests (at least not in Debug mode).
Now my question is: What problems down the road should I expect when violating const correctness in this case? (And would that ever be worth it?)
If the object is actually defined const, then casting away const-ness to modify the object is undefined behavior.
Consider instead using the mutable keyword, which declares an exception to const-ness for a given field; a mutable field is always non-const even when accessed on an object that is considered const in the current context (including from within const methods).
class foo {
private:
int a; // cannot be modified on a const foo
mutable int b; // CAN be modified on a const foo!
};
You could use the mutable keyword for fields related to error tracking.
Of course, a better pattern would be to throw an error object if an error occurs. If your API design does not permit this, making the relevant fields mutable is the correct workaround.
You're not violating const-correctness; you're merely bypassing the built-in language checks for it.
Modifying a non-const thing is fine, even if you had to cast away some constness somewhere along the way (indeed, this is what const_cast is for).
This is generally considered to be a dangerous thing to do, though, and dangerous code to write, so you should modify your interface or design. (This sounds like a good use case for mutable.)
But what runtime errors or weirdness can you expect right now? None at all.
What problems down the road should I expect when violating const correctness in this case? (And would that ever be worth it?)
If the object in question was constructed as a const object, then you definitely run into undefined behavior. However, if the object was constructed as a non-const object, then using const_cast to call a non-const member function is OK.
Simple example:
struct Foo {int f; };
void testFoo(Foo const& foo)
{
const_cast<Foo&>(foo).f = 10; // Analogous to calling a non-const member function.
}
int main()
{
Foo obj1 = {20};
Foo const obj2 = {30};
testFoo(obj1); // ok. obj1 was constructed as a non-const object.
testFoo(obj2); // Not ok. obj2 was constructed as a non-const object.
}

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.

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).

What is the use of passing const references to primitive types?

In a project I maintain, I see a lot of code like this for simple get/set methods
const int & MyClass::getFoo() { return m_foo; }
void MyClass::setFoo(const int & foo) { m_foo = foo; }
What is the point in doing that instead of the following?
int MyClass::getFoo() { return m_foo; } // Removed 'const' and '&'
void MyClass::setFoo(const int foo) { m_foo = foo; } // Removed '&'
Passing a reference to a primitive type should require the same (or more) effort as passing the type's value itself, right?
It's just a number after all...
Is this just some attempted micro-optimization or is there a true benefit?
The difference is that if you get that result into a reference yourself you can track the changes of the integer member variable in your own variable name without recalling the function.
const &int x = myObject.getFoo();
cout<<x<<endl;
//...
cout<<x<<endl;//x might have changed
It's probably not the best design choice, and it's very dangerous to return a reference (const or not), in case a variable that gets freed from scope is returned. So if you return a reference, be careful to be sure it is not a variable that goes out of scope.
There is a slight difference for the modifier too, but again probably not something that is worth doing or that was intended.
void test1(int x)
{
cout<<x<<endl;//prints 1
}
void test2(const int &x)
{
cout<<x<<endl;//prints 1 or something else possibly, another thread could have changed x
}
int main(int argc, char**argv)
{
int x = 1;
test1(x);
//...
test2(x);
return 0;
}
So the end result is that you obtain changes even after the parameters are passed.
To me, passing a const reference for primitives is a mistake. Either you need to modify the value, and in that case you pass a non-const reference, or you just need to access the value and in that case you pass a const.
Const references should only be used for complex classes, when copying objects could be a performance problem. In the case of primitives, unless you need to modify the value of the variable you shouldn't pass a reference. The reason is that references take more computation time than non-references, since with references, the program needs to look up in a table to find the address of the object. When this look-up time is shorter than the copying time, references are an improvement.
Generally, ints and addresses have the same byte length in low-level implementations. So the time of copying an int as a return value for a function is equivalent to the time of copying an address. But in the case where an int is returned, no look up is performed, therefore performance is increased.
The main difference between returning a value and returning a const reference is that you then can const_cast that reference and alter the value.
It's an example of bad design and an attempt to create a smart design where easy and concise design would be more than enough. Instead of just returning a value the author makes readers of code think what intention he might have had.
There is not much benefit. I have seen this in framework or macro generated getters and setters before. The macro code did not distinguish between primitive and non-POD types and just used const type& across the board for setters. I doubt that it is an efficiency issue or a genuine misunderstanding; chances are this is a consistency issue.
I think this type of code is written who have misunderstood the concept of references and use it for everything including primitive data types. I've also seen some code like this and can't see any benefit of doing this.
There is no point and benefit except
void MyClass::setFoo(const int foo)
void MyClass::setFoo(const int& foo)
as then you won't be able to reuse 'foo' variable inside 'setFoo' implementation. And I believe that 'int&' is just because Guy just get used to pass all things by const reference and there is nothing wrong with that.