7 ms·
This is the only good use of a const& shared_ptr which is when you 1) only _might_ want to claim shared ownership of the thing, and 2) the perf of those unneces
by lbrandy 6y ago
This is the only good use of a const& shared_ptr which is when you 1) only _might_ want to claim shared ownership of the thing, and 2) the perf of those unnecessary refcounts matter.
However, you missed a _super_ important caveat of this which is very subtle and very awful. And that is all of the code being executing here between the start of the function and the copy of the shared_ptr is doing it without the protection of the reference count on the shared pointer. It's entirely conceivable that, for example, the `has_widget` function, while executing, invalidates the original shared_ptr passed in and thus makes your eventual use of that shared_ptr invalid.
- PaulDavisThe1st 6y agoHow would it invalidate it?
- bluGill 6y agoYou would need to pass it across threads. At least that is all I can come up with.
- PaulDavisThe1st 6y agothat will not invalidate it. it might have other (negative) implications, but it does not invalidate it.
- bluGill 6y agoIt doesn't automatically invalidate it, but it makes possible things that would invalidate it.
- PaulDavisThe1st 6y agosuch as?
- bluGill 6y agoOther responses (different replies to grandparent) have examples. More realisticly, if you pass a reference to a different thread and return there is no way when to know when the original goes out of scope. Don't do that.
- PaulDavisThe1st 6y agothe whole point of using shared_ptr<T> is to remove the need to "know when the original goes out of scope". you don't need threads for what you're describing: simply passing it to a same-thread method/function which creates a heap-based copy will already complicate your understanding of the lifetime of the referenced object. concrete example: we make wide use of the so-called "signals&slots" pattern, which is more accurately denoted as "anonymous callbacks". we have had a consistent source of serious lifetime mgmt problems caused by (boost|sigc|std)::bind()-ing a shared_ptr<T> into the argument list for the callback - the referenced object now lives for as long as the callback itself lives. This isn't explicit in the code, and even today, probably 12-15 years after we first realized the anti-pattern, we still do it from time to time.
- ridiculous_fish 6y agoSimple example: shared_ptr<int> global; void func(const shared_ptr<int>& v) { global.reset(); *v += 1; // ohno } func(global);
- PaulDavisThe1st 6y agofair enough, but that's fairly stupid programming :) /* XXX the argument might be the same as the global value we're about to modify. API designers, eh? */
- MaulingMonkey 6y agoDoesn't have to be global - could be a member that gets modified in a callback, or that goes out of scope because something else gets deconstructed. I'd also like to inquire as to what nontrivial codebase you've seen that contains no fairly stupid programming. I keep hearing about them, and trying to prove their existence, but so far I've collected more concrete evidence for the existence of bigfoot than I have for the existence of such codebases.
- kevinventullo 6y agoI would assume the caller itself is holding on to the shared pointer.
- gok 6y agoTrue but that's bug-for-bug with passing a const&