Every boost::shared_ptr I see is a cringe-inducing experience. It's not just the atomic memory operation that happens whenever you copy it, it's the programmer who thought that he could just put things in a boost::shared_ptr and it would solve his problems. Now the code is less readable, because you don't know what the lifetime of your resources are! The worst thing is when they get shared across threads, and suddenly you don't know what thread your object's going to be destructed on.
One better alternative to a shared_ptr is a noncopyable shared pointer type. You have to explicitly copy it with a call like
x.copy_from(y);
That this makes the use of reference counted objects more verbose and uncomfortable is not a downside.
Really this should be a noncopyable version of intrusive_ptr, not shared_ptr. Either the object is owned by references on multiple threads and you'll want to be careful about what thread you destroy it from, and perhaps then you'd want to send a release message over some message queue system, or it's a single threaded object and you don't need the overhead of atomic memory operations.
> Now the code is less readable, because you don't know what the lifetime of your resources are!
You're certainly making a valid point; however, as far as howimportant this is, the experience of a lot of people out there points in the other direction.
Consider: the lifetime of a Python object is essentially the same as that of a C++ dynamic object owned by a shared_ptr. But you don't see Python programmers complaining that they can't figure out when their objects are going away. In Java it's even worse; an object's lifetime is pretty much whatever the JVM thinks it ought to be. I have seen complaints about this, but not many, and the JVM's reputation as a platform for serious languages remains pretty strong.
On the other hand, memory leaks in C (and C++) programs have been a major thorn in all our sides for decades.
So, yes, when you get assured destruction by using an object whose lifetime is managed for you, you do lose something. But the experience of programmers all over strongly suggests to me that, for most applications, what you get, is much more valuable than what you lose.
At the risk of sounding like flamebait, it's because Python and Java developers don't know what they are missing without deterministic destructing. Of course there are way to 'code around' it, but knowing the exact lifetime of objects is very often very useful, and often makes for much easier to understand code and easy ways to avoid resource leaks.
What about objects who are referenced by more than one object, and which are linked to resources? try... finally blocks are just a different way of freeing your resources at the end of a block, and won't help with objects which outlive the block they are guarding.
Actually, here is your choice: either you'll have to manage every kind of resource except memory (garbage collected languages), or you'll have to manage only memory (C++).
Yes, that's true, but at the cost of syntactic noise. It's a preference, and one gets used to it I guess, but to me all the try blocks are harder to read than code where variables have a fixed lifetime, so where you in many cases can avoid the extra indent level.
> You're certainly making a valid point; however, as far as how important this is, the experience of a lot of people out there points in the other direction.
That's because I'm talking about C++ and you've somehow decided to talk about something unrelated. Python and Java programmers still care about all resources that aren't object lifetimes.
One better alternative to a shared_ptr is a noncopyable shared pointer type. You have to explicitly copy it with a call like
That this makes the use of reference counted objects more verbose and uncomfortable is not a downside.Really this should be a noncopyable version of intrusive_ptr, not shared_ptr. Either the object is owned by references on multiple threads and you'll want to be careful about what thread you destroy it from, and perhaps then you'd want to send a release message over some message queue system, or it's a single threaded object and you don't need the overhead of atomic memory operations.