Given several changes, I had the impression that useful information would be useful.
1. If not
There are two situations where you should not use smart pointers.
The first is the same situation in which you should not use the C++ class. IE: DLL border if you do not offer the source code to the client. Tell a joke.
The second happens much more often: a smart manager means ownership . You can use pointers to point to existing resources without managing their life cycle, for example:
void notowner(const std::string& name) { Class* pointer(0); if (name == "cat") pointer = getCat(); else if (name == "dog") pointer = getDog(); if (pointer) doSomething(*pointer); }
This example is limited. But the pointer is semantically different from the link, because it can point to an invalid location (null pointer). In this case, it’s great not to use a smart pointer instead, because you do not want to control the lifetime of the object.
2. Smart managers
If you are not writing an intelligent manager class, if you use the delete keyword, you are doing something wrong.
This is a controversial point of view, but having considered so many examples of erroneous code, I no longer risk it. So, if you write new , you need a smart manager for the newly allocated memory. And you need it right now.
This does not mean that you are less than a programmer! In contrast, code reuse that has been proven to work, and not to reuse the wheel over and over, is a key skill.
Now the real difficulty begins: what a smart manager?
3. Smart pointers
There are various smart pointers from there with different characteristics.
Skip std::auto_ptr , which you usually avoid (its copy semantics are screwed in).
scoped_ptr : no overhead, cannot copy or move.unique_ptr : cannot move overhead, cannot copy.shared_ptr / weak_ptr : some overhead (reference counting) can be copied.
Usually try to use either scoped_ptr or unique_ptr . If you need several owners, try changing the design. If you can't change the design and really need more than one owner, use shared_ptr , but be careful of link loops that need to be broken using weak_ptr somewhere in the middle.
4. Smart containers
Many smart pointers are not designed to be copied, so their use with STL containers is somewhat compromised.
Instead of resorting to shared_ptr and its overhead, use smart containers from the Boost Pointer Container . They emulate the interface of classic STL containers, but retain the pointers they own.
5. Moving your own
There are situations when you can quit your own smart manager. Make sure that you do not just miss a function in the libraries that you use in advance.
Writing a smart manager with exceptions is quite difficult. Usually you cannot assume that memory is available ( new may fail) or that Copy Constructor has a no throw guarantee.
It may be acceptable to somewhat ignore the std::bad_alloc and impose that the Copy Constructor number of helpers do not fail ... after all, that boost::shared_ptr does a parameter for its deteter D template.
But I would not recommend it, especially for a beginner. This is a complex problem, and you are unlikely to notice errors right now.
6. Examples
// For the sake of short code, avoid in real code ;) using namespace boost; // Example classes // Yes, clone returns a raw pointer... // it puts the burden on the caller as for how to wrap it // It is to obey the `Cloneable` concept as described in // the Boost Pointer Container library linked above struct Cloneable { virtual ~Cloneable() {} virtual Cloneable* clone() const = 0; }; struct Derived: Cloneable { virtual Derived* clone() const { new Derived(*this); } }; void scoped() { scoped_ptr<Cloneable> c(new Derived); } // memory freed here // illustration of the moved semantics unique_ptr<Cloneable> unique() { return unique_ptr<Cloneable>(new Derived); } void shared() { shared_ptr<Cloneable> n1(new Derived); weak_ptr<Cloneable> w = n1; { shared_ptr<Cloneable> n2 = n1; // copy n1.reset(); assert(n1.get() == 0); assert(n2.get() != 0); assert(!w.expired() && w.get() != 0); } // n2 goes out of scope, the memory is released assert(w.expired()); // no object any longer } void container() { ptr_vector<Cloneable> vec; vec.push_back(new Derived); vec.push_back(new Derived); vec.push_back( vec.front().clone() // Interesting semantic, it is dereferenced! ); } // when vec goes out of scope, it clears up everything ;)