A benevolent case for const_cast? - c++

I've read quite a few discussions that const_cast in C++ is considered wrong and dangerous and should not be used for anything other than backward compatibility with C code. And I generally agree.
However recently I came across the following use case and it made me wonder.
I have some model object, owned by a controller, that is generally non-const. I pass it to a view that should not be able to modify the model object, so it would be logical to declare the object as a const parameter when passed to the view. However the view also makes delegate callbacks to the controller, passing the model object as a parameter (e.g. the user clicked this object). The callback parameter also must be const. In the callback method, the controller wants to make a change to the model, but the model is const so it can't do it.
The two solutions:
use const_cast in the controller's callback method, since it knows the model object is non-const - but it smells.
don't declare the model as const parameter when passed to the view - but then I can't use such a useful tool as the const declaration, which seems very relevant in this case.
Thoughts?

There are two ways to deal with const.
Things are const if this code won't directly change them.
Things are const if this code won't change them.
In this case, the view won't directly change the object. But you want it to indirectly change the object.
Under (2), this means the object isn't const. The view can change the object, if indirectly. It can cause the object to be changed. Saying it is const implies that the views interaction with the object is purely "reading state", not changing the state -- but clicking on the "delete" button of the object and making it delete is a mutating operation.
Under (1), your reference should be const, because you aren't yourself modifying it. Someone else is, under authority granted by their right to do it.
This is one conflict. And (1) is an acceptable way to use const. But when using (1) you should have an alternative route to the object as non-const.
We can see this under vector.erase. It (now) takes const_iterators. Even though those iterators themselves are not permitted to modify the vector, the non-constness of *this provides an alternative access path that permits modification.
In your case, the controller owns the object, so should have a non-const access path to that object. That is the path you should use to do non-const modification of the object.
When the view makes a delegate callback, it might pass an identifier instead of an object -- or, the controller might extract the identifier from the object somehow, and look it back up in its own list of objects.

This is not a good case for const_cast. If the view
accepts the model as a const then it can be given a truly const instance of model. It would then be incorrect to try to pass that instance to the controller. If the reference to the model given to the view can be used to modify the model, then it must not be const.

Related

C++ conventions regarding passing objects (pointer vs reference)

I'd like to work out conventions on passing parameters to functions/methods. I know it's a common issue and it has been answered many times, but I searched a lot and found nothing that fully satisfies me.
Passing by value is obvious and I won't mention this. What I came up with is:
Passing by non-const reference means, that object is MODIFIED
Passing by const reference means, that object is USED
Passing by pointer means, that a reference to object is going to be STORED. Whether ownership is passed or not will depend on the context.
It seems to be consistent, but when I want to pick heap-allocated object and pass it to 2. case parameter, it'd look like this:
void use(const Object &object) { ... }
//...
Object *obj = getOrCreateObject();
use(*obj);
or
Object &obj = *getOrCreateObject();
use(obj);
Both look weird to me. What would you advise?
PS I know that one should avoid raw pointers and use smart instead (easier memory managment and expressiveness in ownership) and it can be the next step in refactoring the project I work on.
You can use these conventions if you like. But keep in mind that you cannot assume conventions when dealing with code written by other people. You also cannot assume that people reading your code are aware of your conventions. You should document an interface with comments when it might be ambiguous.
Passing by pointer means, that object is going to be STORED. Who's its owner will depend on the context.
I can think of only one context where the ownership of a pointer argument should transfer to the callee: Constructor of a smart pointer.
Besides possible intention of storing, a pointer argument can alternatively have the same meaning as a reference argument, with the addition that the argument is optional. You typically cannot represent an optional argument with a reference since they cannot be null - although with custom types you could use a reference to a sentinel value.
Both look weird to me. What would you advise?
Neither look weird to me, so my advise is to get accustomed.
The main problem with your conventions is that you make no allowance for the possibility of interfacing to code (e.g. written by someone else) that doesn't follow your conventions.
Generally speaking, I use a different set of conventions, and rarely find a need to work around them. (The main exception will be if there is a need to use a pointer to a pointer, but I rarely need to do that directly).
Passing by non-const reference is appropriate if ANY of the following MAY be true;
The object may be changed;
The object may be passed to another function by a non-const reference [relevant when using third party code by developers who choose to omit the const - which is actually something a lot of beginners or lazy developers do];
The object may be passed to another function by a non-const pointer [relevant when using third party code be developers who choose to omit the const, or when using legacy APIs];
Non-const member functions of the object are called (regardless of whether they change the object or not) [also often a consideration when using third-party code by developers who prefer to avoid using const].
Conversely, const references may be passed if ALL of the following are true;
No non-mutable members of the object are changed;
The object is only passed to other functions by const reference, by const pointer, or by value;
Only const member functions of the object are called (even if those members are able to change mutable members.
I'll pass by value instead of by const reference in cases where the function would copy the object anyway. (e.g. I won't pass by const reference, and then construct a copy of the passed object within the function).
Passing non-const pointers is relevant if it is appropriate to pass a non-const reference but there is also a possibility of passing no object (e.g. a nullptr).
Passing const pointers is relevant if it is appropriate to pass a const reference but there is also a possibility of passing no object (e.g. a nullptr).
I would not change the convention for either of the following
Storing a reference or pointer to the object within the function for later use - it is possible to convert a pointer to a reference or vice versa. And either one can be stored (a pointer can be assigned, a reference can be used to construct an object);
Distinguishing between dynamically allocated and other objects - since I mostly either avoid using dynamic memory allocation at all (e.g. use standard containers, and pass them around by reference or simply pass iterators from them around) or - if I must use a new expression directly - store the pointer in another object that becomes responsible for deallocation (e.g. a std::smart_pointer) and then pass the containing object around.
In my opionion, they are the same. In the first part of your post, you are talking about the signature, but your example is about function call.

Is there an idiomatic way to constraint the use of shared_ptr::reset

If a call to shared_ptr::reset does not appear in my code for a specific reference counted object, then it would be nice if this could be made explicit and enforceable at compile time.
Is there a standard way to do this?
CLARIFICATION: It is ok if the shared_ptr itself calls reset privately. I just want to make sure I do not call it in my code.
UPDATE: #Brian actually answered it in a comment. const auto p = make_shared... solves the problem for what I declare and if otheres make a non const copy its their problem. I never saw anyone declaring a shared_ptr as const hence somehow I did not think about it.
You cannot forcibly prevent someone from calling a particular public interface function of a class. That's why it's a public interface.
It's not clear what you mean by:
a call to shared_ptr::reset does not appear in my code for a specific reference counted object
The confusing part is what "specific reference counted object" means. You could be talking about a specific instance object of a shared_ptr<T>. In that case, if you want to prevent someone from resetting that particular instance, you can declare it to be a const object. This will also prevent copy/move assignment to it, which can have the same effect.
That doesn't work if the "specific reference counted object" refers to the T held by the pointer, rather than shared_ptr<T>. Someone can take a const object and copy it to a non-const object easily enough. They won't be able to reset the const pointer, but they can still reset a pointer that points to that T.
If shared_ptr<T>::reset offends you enough, you could derive (privately) a new class from shared_ptr, then inherit the interfaces you want except for reset. Then you use your derived class rather than the actual shared_ptr.
Of course, you'll also need to get rid of the copy/move assignment operators, since they can be used to have the same effect as reset. And if you have such a non_rebindable_shared_ptr, then it shouldn't have a default constructor, since creating an empty one would be useless.

Is using a reference as a return value considered as bad coding style?

I got a question regarding to these two possibilities of setting a value:
Let's say I got a string of a class which I want to change. I am using this:
void setfunc(std::string& st) { this->str = st; }
And another function which is able to do the exact same, but with a string reference instead of a void for setting a value:
std::string& reffunc() { return this->str; }
now if I am going to set a value I can use:
std::string text("mytext");
setfunc(text);
//or
reffunc() = text;
Now my question is if it is considered bad at using the second form of setting the value.
There is no performance difference.
The reason to have getters and setters in the first place is that the class can protect its invariants and is easier to modify.
If you have only setters and getters that return by value, your class has the following freedoms, without breaking API:
Change the internal representation. Maybe the string is stored in a different format that is more appropriate for internal operations. Maybe it isn't stored in the class itself.
Validate the incoming value. Does the string have a maximum or minimum length? A setter can enforce this.
Preserve invariants. Is there a second member of the class that needs to change if the string changes? The setter can perform the change. Maybe the string is a URL and the class caches some kind of information about it. The setter can clear the cache.
If you change the getter to return a const reference, as is sometimes done to save a copy, you lose some freedom of representation. You now need an actual object of the return type that you can reference which lives long enough. You need to add lifetime guarantees to the return value, e.g. promising that the reference is not invalidated until a non-const member is used. You can still return a reference to an object that is not a direct member of the class, but maybe a member of a member (for example, returning a reference to the first name part of an internal name struct), or a dereferenced pointer.
But if you return by non-const reference, almost all bets are off. Since the client can change the value referenced, you can no longer rely on a setter being called and code controlled by the class being executed when the value changes. You cannot constrain the value, and you cannot preserve invariants. Returning by non-const reference makes the class little different from a simple struct with public members.
Which leads us to that last option, simply making the data member public. Compared to a getter returning a non-const reference, the only thing you lose is that the object returned can no longer be an indirect member; it has to be a direct, real member.
On the other side of that equation is performance and code overhead. Every getter and setter is additional code to write, with additional opportunities for errors (ever copy-pasted a getter/setter pair for one member to create the same for another and then forgot to change one of the variables in there?). The compiler will probably inline the accessors, but if it doesn't, there's call overhead. If you return something like a string by value, it has to be copied, which is expensive.
It's a trade-off, but most of the time, it's better to write the accessors because it gives you better encapsulation and flexibility.
We cannot see the definition of the member str.
If it's private, your reffunc() exposes a reference to a private member; you're writing a function to violate your design, so you should reconsider what you're doing.
Moreover, it's a reference, so you have to be sure that the object containing str still exists when you use that reference.
Moreover, you are showing outside implementation details, that could change in the future, changing the interface itself (if str becomes something different, setfunc()'s implementation could be adapted, reffunc()'s signature has to change).
It's not wrong what you wrote, but it could be used in the wrong way. You're reducing the encapsulation. It's a design choice.
It's fine. However, you have to watch out for these pitfalls:
the referenced object is modifiable. When you return a non-const reference, you expose data without protection against modifications. Obvious, but be aware of this anyway!
referenced objects can go out of sope. If the referenced object's lifetime ends, accessing the reference will be undefined behavior. However, they can be used to extend the lifetime of temporaries.
The way you used the reffunc() function is considered bad coding. But (as mentioned in the comments), generally speaking, returning references is not bad coding.
Here's why reffunc() = text; is considered bad coding:
People usually do not expect function calls on the left hand of an assignment, but on the right side. The natural expectation when seeing a function call is that it computes and returns a value (or rvalue, which is expected to be on the right hand side of assignment) and not a reference (or lvalue, which is expected to be on the left hand side of assignment).
So by putting a function call on the left hand side of the assignment, you are making your code more complicated, and therefore, less readable. Keeping in mind that you do not have any other motivations for it (as you say, performance is the same, and it usually is in these situations), good coding recommends that you use a "set" function.
Read the great book "Clean Code" for more issues on clean coding.
As for returning references in functions, which is the title of your question, it is not always bad coding and is sometimes required for having cleaner and briefer code. Specifically many operator overloading features in c++ work properly if you return a reference (see operator[] in std::vector and the assignment operator which usually help the code become more readable and less complex. See the comments).

Passing objects vs. Passing references/pointers?

So, as we're all hopefully aware, in Object-oriented programming when the occasion comes when you need somehow access an instance of a class in another class's method, you turn to passing that instance through arguments.
I'm curious, what's the difference in terms of good practice / less prone to breaking things when it comes to either passing an Object, or a Pointer to that object?
Get into the habit of passing objects by reference.
void DoStuff(const vector<int>& values)
If you need to modify the original object, omit the const qualifier.
void DoStuff(vector<int>& values)
If you want to be able to accept an empty/nothing answer, pass it by pointer.
void DoStuff(vector<int>* values)
If you want to do stuff to a local copy, pass it by value.
void DoStuff(vector<int> values)
Problems will only really pop up when you introduce tons of concurrency. By that time, you will know enough to know when to not use certain passing techniques.
Pass a pointer to the object if you want to be able to indicate nonexistence (by passing a NULL).
Try not to pass by value for objects, as that invokes a copy constructor to create a local version of the object within the scope of the call function. Instead, pass by reference. However, there are two modes here. In order to get the exact same effective behavior of passing by value (immutable "copy") without the overhead, pass by const reference. If you feel you will need to alter the passed object, pass by (non-const) reference.
I choose const reference as a default. Of course, non-const if you must mutate the object for the client. Deviation from using references is rarely required.
Pointers are not very C++ - like, since references are available. References are nice because they are forbidden to refer to nothing. Update: To clarify, proper containers for types and arrays are preferred, but for some internal implementations, you will need to pass a pointer.
Objects/values, are completely different in semantics. If I need a copy, I will typically just create it inside the function where needed:
void method(const std::string& str) {
std::string myCopy(str);
...
In fact what you can pass to a method is a pointer to object, a reference to the object and a copy of the object and all of these can also be constant. Depending on your needs you should choose the one that best suits your needs.
First descision you can make is whether the thing you pass should be able to change in your method or not. If you do not intend to change it then a const reference in probably the best alternative(by not changing I also mean you do not intend to call any non-const methods of that object). What are the advantages to that? You safe time for compying the object and also the method signature itself will say "I will not change that parameter".
If you have to change this object you can pass either a reference or a pointer to it. It is not very obligatory to choose just one of these options so you can go for either. The only difference I can think of is that pointer can be NULL(i.e. not pointing to any object at all) while a reference is always pointing to an existent object.
If what you need in your method is a copy of your object, then what you should pass a copy of the object(not a reference and not a pointer). For instance if your method looks like
void Foo(const A& a) {
A temp = a;
}
Then that is a clear indication that passing a copy is a better alternative.
Hope this makes things a bit clearer.
Actually, there's really no good reason for passing a pointer to an object, unless you want to somehow indicate that no object exists.
If you want to change the object, pass a reference to it. If you want to protect it from change within the function, pass it by value or at least const reference.
Some people pass by reference for the speed improvements (passing only an address of a large structure rather than the structure itself for example) but I don't agree with that. In most cases, I'd prefer my software to be safe than fast, a corollary of the saying: "you can't get any less optimised than wrong". :-)
Object-oriented programming is about polymorphism, Liskov Substitution Principle, old code calling new code, you name it. Pass a concrete (derived) object to a routine that works with more abstract (base) objects. If you are not doing that, you are not doing OOP.
This is only achievable when passing references or pointers. Passing by value is best reserved for, um, values.
It is useful to distinguish between values and objects. Values are always concrete, there's no polymorphism. They are often immutable. 5 is 5 and "abc" is "abc". You can pass them by value or by (const) reference.
Objects are always abstract to some degree. Given an object, one can almost always refine it to a more concrete object. A RectangularArea could be a Drawable which could be a Window which could be a ToplevelWindow which could be a ManagedWindow which could be... These must be passed by reference.
Pointers are a wholly separate can of worms. In my experience, naked pointers are best avoided. Use a smart pointer that cannot be NULL. If you need an optional argument, use an explicit optional class template such as boost::optional.

C++ reference to a shared_ptr vs reference

All,
I recently posted this question on DAL design. From that it would seem that passing a reference to an object into a function, with the function then populating that object, would be a good interface for a C++ Data Access Layer, e.g.
bool DAL::loadCar(int id, Car& car) {}
I'm now wondering if using a reference to a boost::shared_ptr would be better, e.g.
bool DAL::loadCar(int id, boost::shared_ptr<Car> &car)
Any thoughts? Does one offer advantages over the other?
What would be the implications of applying const correctness to both calls?
Thanks in advance.
As sbi says, "It depends on what the function does. "
However, I think the most important aspect of the above is not whether NULL is allowed or not, but whether the function stores a pointer to the object for later use. If the function just fills in some data then I would use reference for the following reasons:
the function can still be used by clients who do not use shared_ptr, used for stack objects, etc.
using the function with shared_ptr is still trivial - shared_ptr has dereferencing operator that returns a reference
passing NULL is not possible
less typing
I don't like using "stuff" when I don't have to
If the function needs to store pointer for later use or you anticipate the function might change in such a way that will require storing a pointer, then use shared_ptr.
It depends on what the function does.
In general, a function taking a pointer indicates that callers might call this function even if they don't have an object to pass to it - they can always pass NULL. If that fits the function's spec, then use a (smart) pointer. Passing reference counting smart pointers by references instead copying them is an optimization (and not a premature one, I should add), because it avoids needlessly increasing and decreasing the reference count, which can, in MT environments, be a noticeable performance hit.
A function taking a non-const reference as an argument expects to be passed a valid object that it might change. Callers cannot (legally) call that function unless they have a valid object and they will not call it unless they are willing to have the function change the object's state. If that better fits the function's spec, use a reference.
If you must receive a valid object (i.e. you don't want the caller to pass NULL), then by all means, do not use boost::shared_ptr. Your second example passes a reference to a "smart pointer".... ignoring the details, it is a "pointer to pointer to Car". Because it's reference, the shared_ptr object cannot be NULL.... but it doesn't meant that it can't have a NULL value (i.e. point to a "null" object).
I don't understand exactly why you would think that a reference to a smart pointer would be "better" - does the caller function use smart pointer already?
As for the implications of "const"... do you mean something like
bool DAL::loadCar(int id, const Car& car) {}
?
If yes, it would be counter-productive, you communicate to the compiler the fact that "car" doesn't change (but presumably you want it to change!).
Or do you mean to make the function "const", something like
class DAL{
bool loadCar(int id, Car& car) const;
}
?
In the latter case, you comunicate to the compiler/API user that the method "loadCar" does not modify the DAL object. It's a good idea to do so if this is true - not only that it enables some compiler optimizations, but it is generally a good thing to specify in the "contract" (function signature) that the function makes no modifications to DAL, especially if you make this implicit assumption in your code (this way you make sure that this stays true, and that in the future nobody will modify the "loadCar" function in a way that will change the "DAL" object)
In the first case you simply pass a Car and "fill it" with information. For example, you may create a "default" Car and then fill it. I see one inconvenience in this: it's not very OO to have two classes of Cars: one poor, default, useless, "empty" Car, and one truly filled in Car after it comes from the function. To me, a Car is a Car, so it should be a valid Car (one I can drive from location A to B, for example; one that I can accelerate, brake, start, stop) before and after your function.
I typically work with traditional pointers, not boost (without a problem, by the way) so I really can't comment on the latter alternative.