Also, "if(!p->expired()) p->lock()->foo()" is not thread safe. The last shared_ptr could die on another thread between the test and the lock. Instead, what you want is "if (auto q = p->lock()) q->foo()"
Also, "if(!p->expired()) p->lock()->foo()" is not thread safe. The last shared_ptr could die on another thread between the test and the lock. Instead, what you want is "if (auto q = p->lock()) q->foo()"
Your point is still valid, though -- a shared_ptr should be copied only when you actually want to increase the reference count.
In general, I try to avoid shared_ptr unless I really need reference counting. unique_ptr is much easier to reason about and is much more efficient.
Some might argue that using shared pointers is better for this application, but then you must also deal with potential reference cycles and add weak pointers to the mix eventually, and in addition to these concerns, handle any runtime hits for the reference counting.
https://herbsutter.com/2013/06/05/gotw-91-solution-smart-poi...
>> That's a good point. If the function will eventually lead to some object retaining a reference, then you should use a non-const shared_ptr ref. The assignment into the object will do the copy constructor and that needs a non-const ref. But, you don't need to be making temp object copies along the way. If the function will not lead to something retaining a reference, then you shouldn't be passing the reference retention object to it. Just pass a direct ref to the target object.
Hum? What assignment into the object? Where I'd typically see taking a `const std::shared_ptr<> &` to signal "retaining ownership" would be something like this:
class Foo {
public:
void AppendChild(const std::shared_ptr<Foo> &x) {
children_.emplace_back(x);
}
private:
std::vector<std::shared_ptr<Foo>> children_;
};
Why should Foo:;AppendChild's signature be changed to a non-const ref?This also gives callers the flexibility to std::move into your argument, transferring ownership.
A good rule of thumb is, if you are going to unconditionally take ownership of an object, accept it by value.
void foo(const std::shared_ptr<int>& p);
...
foo(std::make_shared<int>(23));
This will not compile with void foo(std::shared_ptr<int>& p);
since a temporary object cannot be implicitly converted to a non-const reference, only to a const one.