Reputation: 473
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:
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.
Upvotes: 3
Views: 2143
Reputation: 36637
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;
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];const
pointer [relevant when using third party code be developers who choose to omit the const
, or when using legacy APIs];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;
mutable
members of the object are changed;const
reference, by const
pointer, or by value;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
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.Upvotes: 1
Reputation: 238471
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.
Upvotes: 1
Reputation: 1431
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.
Upvotes: 0