From: Jon Kalb (jonkalb_at_[hidden])
Date: 2002-07-19 11:59:38
Steven Kirk [mailto:steven.kirk_at_[hidden]] wrote:
> Peter Dimov [pdimov_at_[hidden]] wrote:
> > This simple (to teach and enforce) rule helps in situations like:
> > f( shared_ptr<T>(new T), g() );
> > where the 'new T' may leak if g() throws.
> > shared_ptr temporaries are best avoided.
> ... I'm not entirely sure I understand the details even now!
If you write:
shared_ptr<T>(new T), g();
This is kind of pointless because the shared_ptr temporary is just
created and then destroyed, but it *is* safe. The coma is a sequence
point and the expression to the left of the comma (shared_ptr<T>(new T))
will be completely evaluated before the expression to right of the comma
(the call to g()). If the call to g() throws, the shared_ptr destructor
will clean up the "new T" pointer. (Actually, it will clean it up either
But when you make a function call, the comma is just a syntactic
separator and no longer an operator that guarantees a sequence point.
The compiler is allowed to evaluate each parameter in any order and
(what is most significant here) it is not required to completely
evaluate one parameter before beginning to evaluate another. So one
legal implementation of this call:
f(shared_ptr<T>(new T), g());
Is for the compiler to do this:
new T then
call g() <might throw> then
call the shared_ptr constructor with the "new T"
call f() with the two parameters
As you can see, if the call to g() throws, the "new T" will leak because
the shared_ptr was never created so the destructor that we are relying
on to clean up the "new T" will not be called.
Peter's rule that "shared_ptr temporaries are best avoided" is a good
one. Not because they are temporaries per say, but because they are
function call parameters which offer exception safety challenges that
are easy to avoid by following the rule and using named objects.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk