Rico Mariani
2 min readApr 8, 2023

--

I didn’t get into it but there are a lot of sharp edges with shared_ptr.

for instance, suppose you have a function with this signature:

void foo(const shared_ptr<Bar> & aBarForMe) {
// do stuff with aBarForMe
}

Can you assume your ref will be good for the function? No. To asssume that you have to assume that someone up your stack is holding the shared pointer for you. If they are, you didn’t need a shared_ptr in the first place, a simple Bar* or Bar& would have done the job. If they aren’t, like say they only have a ref which they got passed to them in some lambda or something like that. You’re screwed, the storage could vanish out from you at any time.

Can you solve this problem by taking a shared_ptr yourself? e.g.

shared_ptr<Bar> holdMyBar = aBarForMe;

No because the pointer could be gone by the time you try to make your copy. You’d have to use a shared_ptr arg in the first place. Costly.

Better answer: do the Rust thing, get your lifetimes under control so that you can make sensible assumptions. Have a smaller number of objects with embedded unique pointers or embedded objects and manage their lifetime. This is kind like if it was ASP you’d have a request object and a response object that had shared_ref but most of the code assumes it is working in the context of a single request/response and doesn’t have to keep upcounting those objects. Or worse yet possibly dozens of sub-objects independently.

The fact is it seems that generally people aren’t thinking about this stuff. It’s full of sharp corners like this. Rust’s approach — be explicit about your lifetimes — has a lot to recommend it. It’s worth emulating even if you don’t get compiler enforcement.

--

--

Rico Mariani
Rico Mariani

Written by Rico Mariani

I’m an Architect at Microsoft; I specialize in software performance engineering and programming tools.

No responses yet