Boost::shared_ptr const&


#1

Jules I need your help winning an argument that it is not worth writing

instead of

The person in question seems to think that somehow the first version is more “optimal” in terms of performance, even though the function in question is only called tens of thousands of times per second (or does it even matter how much it is called)?

My issue is that the version which takes a const reference forces the additional invariant that the object must not lose its last reference (this can only happen in a concurrent scenario). I would rather pass the shared pointer by value, so that the function holds a reference to the object. But this guy thinks its less optimal…premature optimization? How can I reason with him and prevail?

Note that boost::shared_ptr is functionally equivalent to ReferenceCountedObject.


#2

from the comments:

[quote]I found myself disagreeing with the highest-voted answer, so I went looking for expert opinions and here they are. From http://channel9.msdn.com/Shows/Going+Deep/C-and-Beyond-2011-Scott-Andrei-and-Herb-Ask-Us-Anything

Herb Sutter: “when you pass shared_ptr’s, copies are expensive”

Scott Meyers: “There’s nothing special about shared_ptr when it comes to whether you pass it by value, or pass it by reference. Use exactly the same analysis you use for any other user defined type. People seem to have this perception that shared_ptr somehow solves all management problems, and that because it’s small, it’s necessarily inexpensive to pass by value. It has to be copied, and there is a cost associated with that… it’s expensive to pass it by value, so if I can get away with it with proper semantics in my program, I’m gonna pass it by reference to const or reference instead”

Herb Sutter: “always pass them by reference to const, and very occasionally maybe because you know what you called might modify the thing you got a reference from, maybe then you might pass by value… if you copy them as parameters, oh my goodness you almost never need to bump that reference count because it’s being held alive anyway, and you should be passing it by reference, so please do that”

Update: Herb has expanded on this here: http://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters/, although the moral of the story is that you shouldn’t be passing shared_ptr’s at all “unless you want to use or manipulate the smart pointer itself, such as to share or transfer ownership.”[/quote]


#3

Wow nice find! So does all of this apply to ReferenceCountedObjectPtr as well?

Jules do you feel that ReferenceCountedObjectPtr is expensive to pass by value?

Did you transcribe that yourself? Where’d that text come from?


#4

If I’m calling a function with a reference counted object pointer, I’d be more likely to just pass the object’s pointer itself instead. I’d assume that the reference is not likely to become invalid during the call, so the information i’d get from it (the pointer) would surely be okay too (and if I need to store it, it’d be to a reference counted pointer, naturally).

That isn’t advice or anything, I’d be happy for someone to highlight a case/danger I’ve overlooked (or forgotten!) where the reference object itself is a better option. Never really thought too much about it!


#5

Yes, I agree with Herb + Haydxn. My order of preference for the parameter type when passing a smart-pointer would be:

[code]void foo (const Object&); // Best way to do it if the function just needs to use the object and doesn’t need to take its address

void foo (Object&); // Second-best choice if the object can’t be const.

void foo (const Object*); // not as good as using a reference, but handy if the pointer may be null. But don’t use this if the function needs to pass the pointer on to any other functions or store it. Being const should prevent it being accidentally deleted or wrapped in another smart pointer.

void foo (const SmartPointerType&); // best choice if the function needs to pass the pointer to some other function, store it, etc

void foo (SmartPointerType); // the only use-case I can think of for this would be if the function is going to mutate the parameter variable, but that’s probably very uncommon.

void foo (Object*); // Never do this. The ownership of the pointer is ambiguous. If you need the object’s address and the object can’t be const, then always pass a smart-pointer reference as above.[/code]


#6

[quote=“TheVinn”]

Did you transcribe that yourself? Where’d that text come from?[/quote]

Nop. It comes from the stack overflow comments


#7

I’m not sure you do agree with me there, as I think what I was really talking about was the ‘never do this’ approach :smiley:
I guess I’m not really sure I’d class the ownership as ambiguous, since I’d assume that the caller implies some kind of ownership higher up already. I’ve never really given it much thought though, so it’s an interesting lesson :slight_smile: