Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Std::shared_ptr's secret constructor (justsoftwaresolutions.co.uk)
87 points by santaclaus on July 25, 2015 | hide | past | favorite | 10 comments


Interesting, but in most circumstances I think this falls into the "too clever" category. As with most of C++'s weirder features, you really only want to use them when you absolutely have to.

std::shared_ptr is already something that should only be used sparingly. Not because refcounting adds a tiny bit of overhead, but because it can easily lead to confusion about who owns what. If you use the aliasing constructor, it's even more confusing.


"Interesting, but in most circumstances I think this falls into the "too clever" category. As with most of C++'s weirder features, you really only want to use them when you absolutely have to."

The C++ committee has been trying to get ownership semantics to work right for about 20 years now. Remember auto_ptr? They've piled hacks on top of of hacks, and it almost works. Almost.

The Rust borrow checker is the right way to do this. Rust has a clear conceptual model of ownership and a way to enforce it. Trying to emulate that via the type system and templates is like pounding a screw. It sort of works, until it doesn't.

Rust doesn't have all the answers, but the ownership model and borrow checking are a huge advance. Any new attempt to solve this problem has to be at least as good.


The idea is to use shared_ptr when your semantics are such there can be no clear owner. A good example of this is inside a class where you're implementing copy-on-write. Imho, you should always endeavour to avoid using shared_ptr in public APIs. It works especially well where the target is const.


> Good examples of this is inside classes where you're implementing copy-on-write.

Or functional "persistent" datastructures.


> Not because refcounting adds a tiny bit of overhead,

I think you may occasionally find the overhead is more than tiny. Especially when you consider that shared_ptr should also be doing atomics to keep things thread safe.

Anyway, I've heard similar recommendations against overuse of shared_ptr for various reasons and I understand them. But I think it's interesting that one community's recommendations can completely contradict another's. This is before taking into consideration the diverse opinions on what the "proper" C++ is. Compare the C++ world to say, the objc world, where in the latter, everything is refcounted by default, and ARC gives you the equivalent of shared_ptr everywhere all the time. They don't seem to mind.


Personally, I like shared_ptr not just when ownership is unclear, but also for when ownership doesn't matter too much. There's obviously some risk involved if you have complex object graphs set up, but when the graph is simple, I like the ability to pay less attention to lifetime management.

Way I think of it is that using shared_ptr gets me some of the productivity advantages of garbage collected languages, with some of the costs. In areas where performance is not terribly sensitive, this can be a good trade off.

On the other hand, you're absolutely right that this constructor is too clever by half.


I don't. I didn't know this feature existed, so I implemented my own shared pointer type with this capability in order to share sub-objects without having to define certain types with refcounts on all the sub-objects. Actually, the reason was, I didn't even have the capability to define refcounts on the sub-objects, because it was for some protocol buffers value.

Obviously, you would only want to use this feature when you have a reason to want to use it.

std::shared_ptr has no problems with confusion about who owns what, unless you start making cycles. Ownership is shared.


Boost.Python (and Luabind which descends from that) has a similar concept they call Custodian And Ward. There, an object can extend the lifetime of another one, often for the same parent and child rationale in this article. It doesn't come up often in application programming, but in library development it certainly does.

That said, this constructor is not a secret. It's obscure yet occasionally useful, like half of C++.


So the two shared_ptr instances just share the same (heap-allocated) reference counter?


std::shared_ptr<void> is also very interesting, you can put any object in it and the destructor will be called when the shared pointer is destroyed.

I never use it until now but I can see some possible use for it.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: