I have this snippet of code here. The intention is to make a copy of initialData. Since I am not modifying initialData in any way, I figure that I should pass it as a const reference. However, I keep getting this message when compiling.
.\src\Scene\SceneAnimationData.cpp(23)
: error C2662:
'SceneTrackerData::getRect' : cannot
convert 'this' pointer from 'const
SceneTrackerData' to 'SceneTrackerData
&'
#include "SceneTrackerData.h"
void SceneAnimationData::SetupData(const SceneTrackerData &initialData)
{
// getRect(), points() and links() all return const pointers
CloneRect(initialData.getRect());
ClonePoints(initialData.points()->values());
CloneLinks(initialData.links()->values());
}
void SceneAnimationData::CloneRect(const QGraphicsRectItem * initialRect)
{
if (initialRect != NULL)
{
QPointF position = initialRect->scenePos();
QRectF rect = initialRect->rect();
initialRect = new QGraphicsRectItem(rect);
initialRect->setPos(position);
}
}
void SceneAnimationData::CloneLinks(const QList<QGraphicsLineItem*> links)
{
links_ = new QList<QGraphicsLineItem*>(*links);
}
void SceneAnimationData::ClonePoints(const QList<QGraphicsEllipseItem*> points)
{
points_ = new QList<QGraphicsEllipseItem*>(*points);
}
Without the definition of SceneTrackerData, it's hard to say, but likely that function (SceneTrackerData::getRect) is not marked as const.
That is, what is (guessing):
const Rect& SceneTrackerData::getRect(void)
Should be:
const Rect& SceneTrackerData::getRect(void) const
// ^
// |
// does not logically modify the object
It's not clear which is line 23 here; but my guess is that you are calling methods on the object that are not themselves declared as const and thus are not usable by a const object reference.
I am thinking lines like these are illegal:
links_ = new QList<QGraphicsLineItem*>(*links);
points_ = new QList<QGraphicsEllipseItem*>(*points);
in that the passed in links and points are not defined as pointers, but defined values. In order to compile the code, You probably need to either define them like this
const QList<QGraphicsLineItem*>* links
or, instead use them like this
links_ = new QList<QGraphicsLineItem*>(&links); // don't actually do this
However the latter one is potentially a run-time bug, because you are accessing the address of a temp value, which dies after the function body.
Unless QList uses a deep-copy, your app may very likely crash.
I'm not sure as I am no expert C++ programmer, but are your functions getRect() and so on declared const? If not but you know the way you use them is const, you can still use a const_cast to remove the const from your initialData reference.
See for example here: http://docs.oracle.com/cd/E19422-01/819-3690/Cast.html
Or Scott Meyers excellent C++-Books Effective C++ and More Effective C++. At least one of them has an item about constness.
links_ = new QList<QGraphicsLineItem*>(*links);
This could potentially be legal if the * operator is overloaded for the QList class, though I don't think it is. Although as mentioned above, you're probably trying to do
links_ = new QList<QGraphicsLineItem*>(links);
Depending on what the actual constructor takes.
Also, each of those functions should take in the QList by reference, for performance reasons. Right now you copy the entire object twice for each time you call the function. Once to pass it in by value, then once for the construction of the copy.
One thing to remember when dealing with const'ness is that const is NOT guaranteed. Structures exist such as "const_cast" to strip away the const'ness of an object. Having a const object, and using const functions is helpful to signify to other developers that the code should not change the object, not that it cannot change it. See the difference?
void bar(const Foo& f) {
f.setX(5); // compile error, f is const
Foo &f2 = const_cast<Foo&>(f);
f2.setX(5); // compiles just fine
}
The useful part is that unintentional attempts to change the object will result in compiler errors, a determined programmer can easily circumvent these protections.
Related
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.
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...
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why isn't the const qualifier working on pointer members on const objects?
Consider the following class that has a pointer member int *a. The const method constMod is allowed by the compiler even though it modifies the pointer data. Why doesn't the compiler make the pointer data const in the context of the const method? If a was just an int we wouldn't be allowed to modify it in a const method.
class ConstTest
{
public:
ConstTest(int *p): a(p) {}
void constMod() const {
++(*a);
}
int *a;
};
I'm using g++ on linux.
Inside constMod(), the declaration of a is treated as:
int *const a;
which means the pointer has a constant value, not what it points to. It sounds like you are expecting it to be treated as:
const int *a;
which is different.
The pointer itself is not modified, only the data pointed. Even if it sounds strange from a human point of view, from a compiler point of view, none of the member of the class are altered.
It's just an ownership issue... there's no way the compiler can know if the pointed-to object is logically part of the object or not, so it's left for the programmer to police such issues. const members are allowed to perform operations with side effects, as long as they don't modify their own apparent value. It's not really any different from letting them call say std::cout::operator<<() or some other non-const function....
What is const in the above case is the pointer itself. You are not allowed to do ++a;. However, it doesn't prevent you from modifying the data being pointed to.
I believe because here you are trying to change the value where datamember is pointing to.
If you try to modify the data member it would be error.
Meaning, you'll get error if you make a point to something else instead of changing the value
const member functions will not allow you to modify it's members.
In your example, you have a pointer that points an int.
And in the const method, you are modifying the value that it is pointed to but not the pointer itself.
Try giving, ++a, which will actually modify the pointer value and will not be allowed in your const method.
Consider
const T immutable_object0;
const T immutable_object1;
const T* mutable_view = ...a condition... ? &immutable_object0 : &immutable_object1;
// then later you reseat
mutable_view = ...another condition... ? &immutable_object0 : &immutable_object1;
or
const int immutable_data[120]
const int* mutable_view = immutable_data;
for(const int* end = immutable_data + 120; mutable_view != end; ++mutable_view) {
// can't modify *mutable_view
}
It's because pointers don't always have ownership. In some circumstances pointers are views to an object (first example) or are iterators into a raw array (second example). For those cases it doesn't make sense to restrict the operations available on the pointers just because the data pointed to is immutable (or seen as immutable).
The first example is a bit contrived but a valid version of it is when you use a pointer member to implement object association and you don't want the hassle of a reference member. Sometimes the pointed-to types happen to be const.
I know there are few question about const correctness where it is stated that the declaration of a function and its definition do not need to agree for value parameters. This is because the constness of a value parameter only matters inside the function. This is fine:
// header
int func(int i);
// cpp
int func(const int i) {
return i;
}
Is doing this really a best practice? Because I've never seen anyone do it. I've seen this quotation (not sure of the source) in other places this has been discussed:
"In fact, to the compiler, the function signature is the same whether you include this const in front of a value parameter or not."
"Avoid const pass-by-value parameters in function declarations. Still make the parameter const in the same function's definition if it won't be modified."
The second paragraph says to not put the const in the declaration. I assume this is because the constness of a value parameter is meaningless as part of a interface definition. It is an implementation detail.
Based on this recommendation, is it also recommended for the pointer values of pointer parameters? (It is meaningless on a reference parameter since you can't reassign a reference.)
// header
int func1(int* i);
int func2(int* i);
// cpp
int func1(int* i) {
int x = 0;
*i = 3; // compiles without error
i = &x; // compiles without error
return *i;
}
int func2(int* const i) {
int x = 0;
*i = 3; // compiles without error
i = &x; // compile error
return *i;
}
Summary: Making value parameters is useful to catch some logic errors. Is it a best practice? Do you go to the extreme of leaving the const out of the header file? Is it just as useful to const pointer values? Why or why not?
Some references:
C++ const keyword - use liberally?
Use of 'const' for function parameters
An example of when const value parameters are useful:
bool are_ints_equal(const int i, const int j) {
if (i = j) { // without the consts this would compile without error
return true;
} else {
return false;
}
// return i = j; // I know it can be shortened
}
I've read many times that making value parameters in a function const is a bad thing to do because it's unnecessary.
However, I find it occasionally helpful to me as a check that my implementation doesn't do something I don't intend (as in the example at the end of your question).
So, while it may not add value to the caller, it does sometimes add a small bit of value to me as an implementer, and it doesn't take anything away from the caller. So I see no harm using it.
For example, I may be implementing a C function that takes a couple pointers to a buffer - a pointer to the start, and a pointer to the end. I'm going to put data in the buffer, but want to ensure that I don't overrun the end. So inside the function there's code that will increment a pointer as I'm adding data to it. Making the pointer to the end of the buffer a const parameter will ensure that I don't code up a bug that accidentally increments the end boundary pointer instead of the pointer I really should be incrementing.
So a fillArray function with a signature like this:
size_t fillArray( data_t* pStart, data_t* const pEnd);
will prevent me from accidentally incrementing pEnd when I really mean to increment pStart. It's not a huge thing, but I'm pretty sure everyone who has programmed for any period of time in C has run across such a bug.
My take on it:
It's not a bad idea, but the issue is minor and your energy might be better spent on other things.
In your question you provided a good example of when it might catch an error, but occasionally you also end up doing something like this:
void foo(const int count /* … */)
{
int temp = count; // can't modify count, so we need a copy of it
++temp;
/* … */
}
The pros and cons are minor either way.
Unfortunately, some compilers (I'm looking at you, Sun CC!) incorrectly differentiate between arguments declared const and ones not declared so, and you can get errors about undefined functions.
I think this is dependent on your personal style.
It doesn't add or subtract to what clients can pass to your function. In essence it's like a compile-time assertion. If it helps you to know that value won't change, go ahead and do it, but I don't see a big reason for others to do it.
One reason I might not do it is that the const-ness of the value parameter is an implementation detail that your clients don't need to know about. If you later (purposely) change your function so that it actually does change that value, you will need to change the signature of your function, which will force your clients to re-compile.
This is similar to why some people recommend having no public virtual methods (the functions virtual-ness is an implementation detail that should be hidden from clients), but I'm not in that particular camp.
If there is const keyword present; it means value of 'i' (which is const type) can not be modified.
If value of 'i' is changed inside foo function compiler will throw error: "
Can not modify const object
But changing '*i' (i.e. *i = 3;)means you are not changing value of 'i' but value of address pointed by 'i'
Actually,the const function is appropriate for large objects that should not be altered by function.
I like const correctness for situations like this:
void foo(const Bar &b) //I know b cannot be changed
{
//do something with b
}
This lets me use b without fear of modifying it, but I don't have to pay the cost of a copy constructor.
I have a place in the code that used to say
const myType & myVar = someMethod();
The problem is that:
someMethod() returns const myType
I need to be able to change myVar later on, by assigning a default value if the object is in an invalid state. So I need to make myVar to be non-const.
I assume I need to make myVar be non-reference as well, right? E.g. myType myVar?
What is the C++ "correct" way of doing this const-to-nonconst? Static cast? Lexical cast? Something else?
I may have access to boost's lexical cast, so I don't mind that option, but I'd prefer the non-boost solution as well if it ends up i'm not allowed to use boost.
Thanks!
You probably don't need any cast. If you can copy a T, then you can also copy a T const, pathological cases excluded. The copy of the T const need not be a T const itself.
myType myVar = someMethod(); // Creates a non-const copy that you may change.
I wouldn't use the const_cast solutions, and copying the object might not work. Instead, why not conditionally assign to another const reference? If myVar is valid, assign that. If not, assign the default. Then the code below can use this new const reference. One way to do this is to use the conditional expression:
const myType& myOtherVar = (myVar.isValid() ? myVar : defaultVar);
Another way is to write a function that takes a const reference (myVar) and returns either myVar or defaultVar, depending on the validity of myVar, and assign the return value from that to myOtherVar.
A third way is to use a const pointer, pointing it at either the address of myVar or the address of the default object.
const_cast<type without const>()
But, does someMethod() really return const myType? If so, you are making a reference to a temporary -- it will be destroyed and your reference will be bad. Change myVar to non-ref (so it copies) -- no need to declare it const in that case. Or, if someMethod() returns a reference, use the const_cast if you must (but you are changing something that someMethod thought wouldn't change).
There's no "C++" way (not only to this, but to anything).
The bad way is to use a const_cast, but the behavior will then be undefined (read: don't do that).
What you should do is copy the object and then modify the copy. It's the only proper way to deal with immutable objects.
Try the following
myType& mutableMyVar = const_cast<myType&>(myVar);
In general removing const is a bad idea though. The caller method returned you a reference to a variable it believes will be treated as const. If you violate this assumption by removing the const and modifying the variable you could put either object into a valid state.
It may be legal in your particular case but in general this is something to be avoided
You can creat an object from the const object using copy constructor or something assignment operator and then modify it.
But I think you would be better off seeing why the function was returning const type in the first place. There would have been a reason why it was declared const. If you are very sure that that is what you wanted, you can always const_cast away the constness like this:
T obj1 = const_cast<T&> (obj);
What is the C++ "correct" way of doing this const-to-nonconst? Static cast? Lexical cast? Something else?
There is no C++ way. For one reason or another, the author of that class decided that you should not be able to modify the instance through this method.
If you were the author, you could make it return a non-const reference. But those are still suspicious, unless the class really has no business hiding it from you (e.g like vector doesn't hide what it holds for you, and just hides how it holds stuff for you).
A better way (depending on what this is all about) might also be not to expose members for external manipulation, but rather provide a method that does this manipulation for you. For example:
class BadPosition
{
int x, y;
public:
int& get_x() { return x; }
int& get_y() { return x; }
//...
};
BadPosition p;
p.get_x() += 1;
p.get_y() += -1;
class BetterPosition
{
int x, y;
public:
void move(int x_inc, int y_inc) { x += x_inc; y += y_inc; }
//...
};
BetterPosition p;
p.move(1, -1);
If you need this to put the class in a valid state later, then perhaps consider making its constructor do that. If you cannot do that, at least provide an Init() method, so as not to make such a complicated class rely entirely on being externally manipulated into something usable.
There may be of course other ways not requiring a cast, e.g you could create a copy, modify that, and then use the modified copy to replace the whole instance with another one (assuming this is enough to construct it):
X x;
...
Y y = x.get();
y.modify();
x = X(y);
Edit: So the class returns by value? In this case there should be no way to modify the instance in the class, since all you get is a copy in the first place. You can reference that with a const reference, but even if you cast away constness from that reference, you are still referencing a temporary.
My reply above assumed it returned a const reference, since that would seem a more sensible thing to do (I haven't seen people often return by const value, although probably there are those who strongly recommend it).