Quote:Original post by XaiKey to remember is that C++ doesn't have a single facility not useful and needed in some case (except a few things who's only need is backwards compatibility - and the stupid keyword "auto").
Actually, "auto" is probably going to be made useful again in the next revision of the C++ standard.
for (std::map<string, double>::const_iterator b = m.begin(), m.end(); b != e; ++b){}// becomesfor (auto b = m.begin(), e = m.end(); b != e; ++b){}// (though I think a foreach construct is being considered, also)
To the O.P:
A good rule of thumb is this: Make sure that the lifetime of every object you create is handled by the program and not by the programmer. This is what happens when you create objects on the "stack", in automatic storage, as in your second code snippet.
In general, if you're having to write delete explicitly, you're doing something wrong, or at least you're causing problems for yourself.
Always prefer to handle resources such as pointers to dynamically allocated objects with a wrapper class e.g.
boost::shared_ptr<Pirulo> p(new Pirulo());// no need to delete explicitly
Pointers don't have destructors, so they don't know to delete what they point to. By wrapping a pointer to a dynamically allocated object in something such as boost::shared_ptr<>, we are effectively giving it a destructor, which knows when and how to clean up after itself.
But surely one manual new/delete pair isn't so bad? Well, it isn't at the moment. But if you add extra return statements before the delete is invoked, you will have to remember to delete the pointer again, just before each return statement.
Similarly, if any function call made between the time you new and delete your object can throw an exception, you will have a memory leak unless you explicitly add try/catch blocks around those functions. If the function f() in your example throws an exception, you'd leak memory and any other resources associated with a Pirulo object. Even if you know that f() won't throw now, there's no reason that you won't change it at some point in future in such a way that it may release an exception.
Adding all the extra delete statements and try/catch scaffolding can become a real PITA and obfuscates the code no end. I wrote about this in more detail,
here.
The simplest way of all to handle objects, of course, is to create them on the stack (as in your second chunk of code) and give them value semantics. Then the object destructors will do the right thing, even in the face of early-returns and exceptions, relieving the programmer of the burden.
The C++ standard containers expect value semantics of your objects, so its a good thing to strive for.
By the way, you can't have a reference-to-void, so Meyers can't have recommended it. Meyers recommends doing what I've just spelled out;
1. Creating objects with value semantics, where possible (look up "the rule of three").
2. Putting objects that are unable to clean up after themselves in a wrapper object that will be able to do that for them.