Not mentioned is passing shared_ptrs as parameters by value.  People do it all the time because &quot;passing pointer parameters is as cheap as it gets, right?&quot;  But, shared_ptr&#x27;s thread safety means that each copy involves a full trip past all cache levels to actual DRAM.  100+ cycles each.  They are not pointers.  They are small yet heavy objects and should be passed by reference.  Copying implies assuming shared ownership and should not be done lightly.<p>Also, &quot;if(!p-&gt;expired()) p-&gt;lock()-&gt;foo()&quot; is not thread safe.  The last shared_ptr could die on another thread between the test and the lock.  Instead, what you want is &quot;if (auto q = p-&gt;lock()) q-&gt;foo()&quot;