|#3 can be fixed with a unique_ptr.|
I know that. But you were discussing how shared_ptr stacks up against raw pointers. #3 is a problem with raw pointers that shared_ptr solves. Yes, unique_ptr also solves it.
|#1 is only half fixed given that you'll have to figure out whether every reference is dead in order to ascertain that it's deleted.|That's not true. If you have a shared_ptr that's non-null, then you can be 100% sure it's a valid pointer.
It's technically possible that won't be true, but you would have to deliberately sabotage yourself and/or be passing around raw pointers and manually deleting them for this to happen. So again it comes down to being a problem with raw pointers and manual deletion.
EDIT: Sorry, I thought #1 was a different item. You're right. But that's a problem with the shared ownership paradigm, not really with shared_ptr. You'd have the same problem with raw pointers sharing ownership.
So yes... shared_ptr only half fixes it. But raw pointers are no more "fixed" than shared_ptrs are.
|#4 can easily be fixed by setting the pointer to NULL after deletion which can be wrapped in a macro/function instead of using unsafe delete. If different resources hold the same pointer (meaning one does not hold a reference of another pointer, but a true copy of the pointer) then that is "bad design".|
Yes that is arguably bad design. But it's still a problem that raw pointers have that shared_ptr does not.
Remember: shared_ptr is for shared ownership. If you think shared ownership is not applicable or is a bad design for a particular problem... then shared_ptr is not the right tool. But in instances where you need shared ownership, shared_ptr solves all these problems whereas raw pointers are extremely difficult to deal with.
|Holding a reference to another pointer and using a function rather than delete will prevent deleting that pointer and require you leave it up to whatever owns that pointer to delete it, at the cost of nothing.|
It adds the cost of another indirection... which is not nothing. If you're nitpicking over the performance of reference counting... I'm going to nitpick over the performance of extra levels of indirection. In fact, the extra indirection is probably slower than doing the reference count for this situation... as you only reference count on construction/destruction, but you do the extra indirection every time the reference is accessed.
But anyway, ignoring the possibility that this may be slower, it still only works until the original pointer goes out of scope.. then you have dangling references. So this does nothing to solve the problem.
And of course you could just keep a reference to the shared_ptr as well... which is exactly the same syntactically... costs the same amount.... but also means you don't have to manually delete or remember to call a "safe delete" function.
Also... the solution of calling a separate safe delete function is introducing yet another way for the programmer to screw up. So that might be a 5th problem with raw pointers that shared_ptr solves: "5) forgetting to NULL the pointer after deleting it"
Let's come back to the original purpose here, though.
You're saying newbies should not just throw shared_ptr everywhere. I agree with that
. What I don't agree with is saying that newbies should use raw pointers for memory management. In fact I don't think anyone
should use raw pointers for memory management in C++. There is no advantage to it, and it's extremely error prone (especially with newbies).
So rather than discuss "shared_ptr vs. raw pointer".... I'd like to shift this back to a more general "raw pointer vs. smart pointer" debate.
Can you give me any situation where maintaining ownership with a raw pointer provides benefit over doing so with an appropriate smart pointer or other RAII object? Because I can't think of a single one.