Your third option is totally different than the first two. The type is different. I'm going to talk about the first two options (and present some more).
func(vector<obj> )
- pass by value
Changes made internally are not reflected on the outside. Theoretically, a copy is made, yes. However, the semantics are different. You couldn't pass by value and achieve the same thing. Also, with move semantics in C++11, a situation where a pass-by-value and pass-by-reference behave the same has the same efficiency, because the vector isn't copied, but moved.
func(vector<obj>*)
- pass a pointer by value
A copy of the pointer is made. Internally, changes to the pointer itself aren't reflected on the outside. Changes to the vector
it points to are. So the effect is different from the option before - if you want to make changes that aren't reflected on the outside, you need a copy anyways.
func(/*const*/ vector<obj>&)
- pass by reference
If not const
, changes are reflected on the outside. Again, different semantics - if you're modifying the object, changes will be reflected on the outside. If you don't want that (changes reflected on the outside), you need a copy anyway.
The decision between the three isn't trivial.
The second one is closer to what you'd do in C, so I'd avoid it if I could (not needed + you can achieve the same effect with pass-by-reference + no naked pointers).
If you want to modify the object inside the function and have the changes reflected on the outside, use pass by non-const
reference. This couldn't be achieved by pass-by-value anyway.
If you don't plan on modifying the object, use pass by const
reference. This guarantees no copy is made, and that you're not modifying the object.
If you want to modify the object but not have the changes reflected on the outside, use pass-by-value. In situations where changes wouldn't be reflected on the outside, a copy is avoided (i.e. when you pass a temporary) and a move is preferred. In situations where they would, you'd need a copy of the original object anyway.