Quote:
Originally Posted by
CornedBee
Do what? Dereference them and pass a reference to the object to functions? Of course! If a function doesn't need the information that the object passed to it is ultimately managed by a smart pointer, by all means hide that information. The less a function knows, the better. The less a function can do, the better. Give every component of your code the absolute minimum information and capabilities it needs to do what it should. Everything beyond that makes the program harder to understand. That's the rule that ultimately leads to such things as discouraging global variables, using access control for encapsulation in classes, keeping your code const-correct and so on.
The only problem (or the biggest anyway) I have with that is that you're leaving the function wide open to free the memory and crashing the class. Unless
Quote:
It makes no sense to call Delete on any smart pointer if you don't have the guarantee that the pointee is actually deleted. With a reference-counting pointer, that's the general case. Therefore, it shouldn't have a method called Delete.
No, it's not. New is guaranteed (unless an error occurs) to allocate memory and make the pointer point to it. If Delete were the opposite, it would guarantee to free that memory and make the pointer point to nothing. But because the pointer does reference counting, Delete only guarantees the latter. Thus, it's not an opposite of New and shouldn't be called Delete. The same goes for Erase. Erase is more ambiguous in its meaning, but it's also non-idiomatic for memory handling. The name is used in the standard containers for the deletion of individual elements. RemoveRef makes sense in the context of the reference-counted smart pointer, but it leaks the idea of reference counting into the name of a method that could well exist without it. This means that a smart pointer using a different memory management method (say, a scoped_ptr or a unique_ptr) cannot have the same name for the same functionality without being misleading, and that means that the various smart pointers have different names for the same functionality, leading to a steeper learning curve for each one. Consistency in interfaces is important.
Among my names, Clear is my least favourite. It's taken again from the containers, where it means freeing everything, completely emptying the container. Not the best association, but it still indicates a disassociation of the object from whatever is behind it.
This disassociation is the primary focus of the name Release. It releases the pointer it has a hold on back its origin. It disassociates from the pointer. There's now one owner less of the memory. The two big disadvantages of the name come from its association. First, the auto_ptr class uses release() for real disassociation, i.e. it passes control over the pointer lifetime back to the programmer. That's not what happens for a reference-counted pointer, because the pointer cannot guarantee that no other pointer exists. Second, Microsoft's COM (and by copying, Mozilla's XPCOM) specifies that every object has a method called Release, but due to the internally reference-counted nature of COM objects, there is no nulling out pointers, and definitely no safety.
So we're left with Reset. Reset returns to the pointer nature of the smart pointer, simply meaning "return the pointer to its original state", that state being null. That's all that Reset means: set the pointer to null. If the pointer happens to manage the memory of the pointee in such a way that the pointee is deleted as a consequence, that's fine. I like this name most of all.
In such case, I like Release() best of all. Release is used by COM after all, which also has reference counting.
Quote:
No, it doesn't. The purpose of smart pointers is to impose an automated memory handling policy. What exactly this policy does depends on the smart pointer.
Your reference-counted smart pointer has the policy, "As long as at least one pointer to a memory block exists, the memory block is kept alive."
If main() calls foo() and passes its sole pointer object by non-const reference, it's saying, "Here's my pointer, along with whatever it points to and the power to modify what it points to." If main() needs a guarantee that the memory is still alive after the call, it shouldn't have passed its only pointer to that memory by non-const reference. It should have created a copy of the pointer first.
I should probably pass it by const reference, but it seems I can't get the class to work with const since the locking and unlocking fails if the functions are const (go figure?).