Given the following code:
class foo;
foo* instance = NULL;
class foo
{
public:
explicit foo(int j)
: i(j)
{
instance = this;
}
void inc()
{
++i;
}
private:
int i;
};
Is the following using defined behavior?
const foo f(0);
int main()
{
instance->inc();
}
I'm asking because I'm using a class registry, and as I don't directly modify f it would be nice to make it const, but then later on f is modified indirectly by the registry.
EDIT: By defined behavior I mean: Is the object placed into some special memory location which can only be written to once? Read-only memory is out of the question, at least until constexpr of C++1x. Constant primitive types for instance, are (often) placed into read-only memory, and doing a const_cast on it may result in undefined behavior, for instance:
int main()
{
const int i = 42;
const_cast<int&>(i) = 0; // UB
}
Yes, it is undefined behavior, as per 7.1.5.1/4:
Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a const object during its lifetime (3.8) results in undefined behavior.
Note that object's lifetime begins when the constructor call has completed (3.8/1).
This may be one of the rare cases where the not very known mutable keyword could be used:
mutable int i;
i can now be changed even if the object is const. It's used when logically the object doesn't change, but in reality it does.
For example:
class SomeClass
{
// ....
void DoSomething() { mMutex.lock(); ...; }
mutable Mutex mMutex;
}
In DoSomething() the object doesn't logically change and yet mMutex has to change in order to lock it. So it makes sense to make it mutable, otherwise no instance of SomeClass could be const (assuming you lock the muetx for every operation).
If you define a const instance of the object, then cast away the const-ness, and modify the contents of the object, you get undefined behavior.
From the sound of things, what you want is exactly the opposite: create a non-const instance of the object, then return a const pointer to that object to (most of) the clients, while the "owner" retains a non-const pointer to the object so it can modify members as it sees fit.
You'd typically manage a situation like this by defining the class with a private ctor, so most clients can't create objects of the type. The class will then declare the owner class as a friend, so it can use the private ctor and/or a static member function to create instances (or often only one instance) of the object. The owner class then passes out pointers (or references) to const objects for clients to use. You need neither a mutable member nor to cast away constness, because the owner, which has the "right" to modify the object, always has a non-const pointer (or, again, reference) to the object. Its clients receive only const pointers/references, preventing modification.
Calling a non-const (by declaration) member function on a const object is not illegal per se. You can use whatever method you wish to work around the compiler restrictions: either an explicit const_cast or a trick with constructor as in your example.
However, the behavior is only defined as long as the member function you are calling does not make an attempt to actually physically modify the object (i.e. modify a non-mutable member of the constant object). Once it makes an attempt to perform a modification, the behavior becomes undefined. In your case, method inc modifies the object, meaning that in your example the behavior is undefined.
Just calling the method, again, is perfectly legal.
It's hard to tell the intent with these arbitrary names. If i is intended as just a use counter, and it isn't really considered part of the data, then it is perfectly appropriate to declare it as mutable int i; Then the const-ness of an instance is not violated when i is modified. On the other hand, if i is meaningful data in the space being modeled, then that would be a very bad thing to do.
Separately from that, though, your example is a bit of a mess for what you seem to be asking. foo* instance = NULL; is effectively (if confusingly) using a NULL as a numeric zero and initializing instance, which is not const; then you separately initialize f, which is const, but never reference it.
Under GCC, at least, your constructor should be explicit foo(int j) with the word int.
However, it's perfectly fine to have two pointers to the same value, one const and the other not.
Why dont you make use of const cast ?
Any reason to make object as const eventhough its state is not constant?
Also make following change :
explicit foo(int j = 0) : i(j)
{ instance = this; }
Related
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.
}
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.
C++ methods allow a const qualifier to indicate that the object is not changed by the method. But what does that mean? Eg. if the instance variables are pointers, does it mean that the pointers are not changed, or also that the memory to which they point is not changed?
Concretely, here is a minimal example class
class myclass {
int * data;
myclass() {
data = new int[10];
}
~myclass() {
delete [] data;
}
void set(const int index) const {
data[index] = 1;
}
};
Does the method set correctly qualify as const? It does not change the member variable data, but it sure does change the content of the array.
What can a 'const' method change?
Without explicitly casting away constness, a const member function can change:
mutable data members, and
any data the class has non-const access to, irrespective of whether that data's accessible:
via member variables that are pointers or references,
via pointers or references passed as function arguments,
via pointers or references returned by functions,
directly in the namespace or class (for static members) containing it.
These restrictions apply to operations of data members and bases (in the OO sense) too. More explicitly, a const member function operating on *this's data members or bases, when they're of class/struct/union type, can only call their const member functions (if any), and can only write to their mutable data members (if any).
(A const member function can also change any non-const local variables and by-value parameters, but I know that's not what you're interested in).
const data members can call other const member functions, which will have these same abilities and restrictions.
Eg. if the instance variables are pointers, does it mean that the pointers are not changed, or also that the memory to which they point is not changed?
It means the pointers can't be (easily/accidentally) changed. It does not mean that the pointed-to memory can't be changed.
What you've stumbled on is the logical incorrectness of a const function changing pointed-to or referenced data conceptually owned by the object. As you've found, the compiler doesn't enforce the const correctness you may want or expect here. That's a bit dangerous, but means constness doesn't need to be explicitly removed for pointers/references to other objects which may be changed as a side-effect of the const function. For example, a logging object. (Typically, such objects are not logically "owned" by the object whose const function is operating on them.) The key point is that the compiler can't reliably distinguish the type of logical ownership an object has over pointed-to data, so it's got to guess one way or the other and allow the programmer to either override, or not be protected by const-ness. C++ forgoes the protection.
Interesting, I've heard Walter Bright's D language flips this default, making pointed-to data const by default in const functions. That seems safer to me, though it's hard to imagine how often one would end up needing to explicitly cast away constness to allow wanted side-effects, and whether that would feel satisfyingly precise or annoyingly verbose.
Most succinctly, it means that the type of this is const T * inside const member functions, where T is your class, while in unqualified functions it is T *.
Your method set does not change data, so it can be qualified as const. In other words, myclass::data is accessed as this->data and is of type int * const.
There are two aspects to this question:
what does const mean to the compiler?
how does const apply when it cannot be validated by the compiler?
Question 1
The first is rather simple. The compiler validates that no data members are modified (unless they are qualified as mutable). It validates this recursively: for any user-defined types, it checks that no non-const methods are invoked. For built-in types, it validates that they are not assigned.
The transformation for pointers is T* to T*const (const pointer), not const T* (pointer to const). This means that the compiler does not validate that the object pointed to is not modified. Obviously, this leads to question 2.
Question 2
How does const apply when not validate by the compiler? It means whatever it should mean to your application. This is usually referred to as logical const. When to use const with respect to logical const-ness is subject to debate.
const when applied to a method means:
This means that the state of the object will not be changed by the method.
This means any members that are part of the objects state can not be modified, nor can any functions that are not also const be called.
As this relates to pointers. It means the pointer (if it is part of the state) can not be changed. But the object the pointer points at is part of another object so that means you can call non cost methods on this object (as it is not part of the state of this object).
const basically prevents changing the class instance members' values inside the function. This is useful for more clearer interface, but pose restrictions when using inheritance for example. It's sometimes a little bit deceiving (or a lot actually), as in the example you posted.
const would be most appropriate for Get functions, where it is obvious that the caller is reading a value and has no intentions of changing the object state. In this case you would want to limit the inherited implementations as well to adhere to constness, to avoid confusion and hidden bugs when using polymorphism.
For example
class A{
int i;
public:
virtual int GetI() {return i;};
}
class B : public A{
public:
int GetI() { i = i*2; return i;}; // undesirable
}
changing A to:
virtual int GetI() const {return i;};
solves the problem.
Would it be possible for a public function to return a pointer to a private variable in the class. If so / if not, what would happen? would it crash or is there anything highly unsafe about this? Can the pointed data be read or written to?
Thanks
Yes, a member function may return a pointer (or reference) to a private data member. There is nothing wrong with this except that in most circumstances it breaks encapsulation.
The data member can certainly be read via the returned pointer or reference. Whether or not it can be written to depends on whether the returned pointer or reference is to a const-qualified object (i.e., if you return a const T*, you won't be able to modify the pointed-to T). For example:
class Example
{
public:
int* get() { return &i; }
const int* get_const() const { return &i; }
private:
int i;
};
int main()
{
Example e;
int* p = e.get();
int a = *p; // yes, we can read the data via the pointer
*p = 42; // yes, we can modify the data via the pointer
const int* cp = e.get_const();
int b = *cp; // yes, we can read the data via the pointer
*cp = 42; // error: pointer is to a const int
}
Yes it can be returned and it can be read and written to. It is no more or less dangerous than taking the address of any other variable. Public/private/protected are syntactical constructs that are checked at compile time, and they aren't "contagious" or part of the type of something.
A private member is no different from a public member, or any other type of instance. So, yes, you can take pointers to them, and return them.
When taking pointers to any instance-based member, you have to be careful that the parent class is not deleted and doesn't go out of scope, unless you take that pointer and make a true copy of the data/object it points to. If it is deleted or goes out of scope, the pointer becomes a dangling pointer, and you can't use it anymore without your app exploding (or working on non-existent objects, and thus making your program do crazy unexpected things, but not crashing).
Design considerations:
Exposing any of your internal implementation details is potentially a violation of encapsulation. However, if you only want to encapsulate HOW the object you're returning is created/retrieved, then this is a reasonable solution. This would allow you to change the class to get the member object some other way (like querying a file, or an internal dictionary) without breaking code that calls these methods.
"would it crash or is there anything highly unsafe about this? Can the pointed data be read or written to?"
private/protected/public have no effect whatsoever at runtime, so they can't influence the program execution or even crash the program. They are checked at compile time and just cause your compiler to throw an error while compiling if there is a violation.
The const qualifier won't protect you on those cases. Considering James's response, please try to cast the const int * to int *
int* cp = (int*)e.get_const();
You will still be able to modify.
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).