Boost logo

Boost :

From: Jonathan Turkanis (technews_at_[hidden])
Date: 2005-02-13 18:19:21


Chris Just wrote:
> Jonathan Turkanis wrote:
>>> I wanted to create a very simple AutoPtr that was essentially the
>>> same as the STL auto_ptr (and backwards compatible with it).
>>
>> Unfortunately, you haven't (see below). Furthermore, auto_ptr is
>> widely recognized as unsafe because it is too easy to transfer
>> ownership unintentionally.
>
> Of course you can unintentionally transfer ownership if you don't
> know what you're doing. ;)

The problem is that the code which transfers ownership appears innocuous on the
surface, because auto_ptr allows transfer of ownership with the same syntax
ordinarily used for copying:

    void f()
    {
         auto_ptr<int> ptr(new int);
         auto_ptr<int> ptr2(ptr); // ptr is now empty.
    }

If auto_ptr were the best that could be implemented, we would have to settle for
it. But move_ptr allows transfer of ownership to be expressed more safely.

> I believe that's why you're not supposed to pass an auto_ptr to a
> function -- instead you pass the pointer itself with .get(). You
> can't stop everyone from shooting themselves in the foot.

Declaring a function to take an argument of type auto_ptr<...> is one way to
signal that ownership is being transfered to the function. It also ensures that
the managed object will be deleted, unless the function takes explicit steps to
cause a leak. Passing raw pointers defeats this system.

>>>> I only looked very briefly, but I don't see how your auto_ptr can
>>>> be returned from functions. Also, why do you need the m_Owner
>>>> variable?
>>>
>>> Correct me if I'm wrong, but wasn't there a specific reason why the
>>> STL auto_ptr was made so it couldn't be passed to or returned from a
>>> function?
>>
>> This was true of the initial version. The standard version, which is
>> version 3, implements a flavor of move semantics (and it doesn't
>> quite work).
>
> I'm using the version that comes with Visual C++ 6.0, whatever
> version that is.

I believe its version 2, roughly speaking.

>>> Anyways, if you want to pass or return the pointer to/from a
>>> function, just use the .get() or .release() functions.
>>
>> But this subverts the resource management system.
>
> How? If you pass a pointer to a function, you shouldn't be deleting
> it inside that function anyways (so pass it with .get()),

What if you want to transfer ownership to the function, as is often the case?

> and if you
> return a pointer from a function, you can save it in a new AutoPtr so
> it will get deleted automatically...

This depends on the calling code to do the right thing. If you return an
auto_ptr, the managed object will be freed even if the calling code choses to
ignore the return value.

>>> I need the m_Owner variable to tell me if I own the pointer before I
>>> delete it.
>>
>> For auto_ptr, checking that the stored pointer is non-null should be
>> sufficient.
>
> I don't set my pointer to NULL when I release() it, I just set
> m_Owner = false.

This behavior is not compatible with std::auto_ptr.

> I've also run some speed comparisons between auto_ptr and AutoPtr and
> (on Windows at least) they appear to be virtually the same speed when
> doing the same operations.
> I'm wondering what the speed comparisons would be between auto_ptr
> and some of the other smart pointers that you mentioned?

move_ptr has the same overhead as auto_ptr. For other varieties of pointers, see

http://www.boost.org/libs/smart_ptr/smarttests.htm
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1450.html

and the April 2004 CUJ article "Smart Pointer Reloaded (IV): Finale" by David
Held and Andrei Alexandrescu.

Jonathan


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk