|
Boost : |
From: David Abrahams (david.abrahams_at_[hidden])
Date: 2002-01-18 08:58:36
----- Original Message -----
From: "Peter Dimov" <pdimov_at_[hidden]>
> > struct Base { Base(); ~Base(); };
> > struct Derived : Base { Derived(); ~Derived(); };
> >
> > void unsafe()
> > {
> > shared_ptr<Base> b(new Derived);
>
> The expression "delete get()" invokes undefined behavior, therefore the
code
> is ill-formed.
1.3.14 well-formed program
a C++ program constructed according to the syntax rules, diagnosable
semantic rules, and the One Defini-
tion Rule (3.2).
So, I think "buggy" would be a better term here ;-)
> > b.reset(); // equivalent to delete (Base*)(new Derived)!!
> > };
> >
> > That's because, as long as shared_ptr<Base> allows construction from
> > a Derived*, it doesn't matter where the Derived* is obtained from.
> > Unfortunately, that means that tricks such as auto_ptr_ref can't save
> > us here.
> >
> > How about adding an additional constructor:
> >
> > template<typename Y>
> > explicit shared_ptr(Y* p);
>
> Doesn't help.
>
> Base * p = new Derived;
> shared_ptr<Base> b(p);
This is one reason I think it should be possible to configure a shared_ptr
so that it can't be constructed from a raw pointer. Here's another:
shared_ptr<X> p(new X);
f(p.get());
void f(X* p)
{
shared_ptr<X> y(p); // double-deletion
}
I've seen this mistake made by novices and experts alike.
Instead, there ought to be a family of static factory functions, so:
shared_ptr<Y> p = shared_ptr<Y>::create(arg1, arg2, arg3);
is equivalent to:
shred_ptr<Y> p(new Y(arg1, arg2, arg3));
-Dave
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk