Topic: auto_ptr


Author: lg <lg@mail.ndirect.co.uk>
Date: 1997/12/15
Raw View
I have noticed that the definition of auto_ptr seems to have undergone an
about face again in the approved standard. I hope this will mean that
unexpected lost of ownership (through programming erros) will result in
clear and immediate errors (dereferencing of null pointers) in most systems.

Could someone point me in the direction of some more detail on the standard
auto_ptr? I have looked at Stroustrup's revisions/errata of his C++
programming language III which mentions autoptr. Is there a reference
implentation someone has put forward? Would this autoptr work under most
current implentations or would it be dependent or recent changes in overload
resolution? The "STLPort" based on the SGI modified STL seems to support the
previous version of auto_ptr with an ownership bool.

Thanks a lot
Llew
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: "greg" <dont@spam.me>
Date: 1997/12/16
Raw View
> I have noticed that the definition of auto_ptr seems to have undergone an
> about face again in the approved standard. I hope this will mean that
> unexpected lost of ownership (through programming erros) will result in
> clear and immediate errors (dereferencing of null pointers) in most
systems.

Yes.

> Could someone point me in the direction of some more detail on the
standard
> auto_ptr? ...

Here is the proposal that we accepted in London:
------------------------------------------------------------------------

                       Doc. No.:  J16/97-0090R1=WG21/N1128R1

                       Date:      November 14, 1997
                       Project:   Programming Language C++
                       Reply to:  Bill Gibbons <bill@gibbons.org>
                                  Greg Colvin  <greg@imrgold.com>


                         Fixing auto_ptr.



The auto_ptr specified in CD-2 has proved unpopular and dangerous,
primarily because the const arguments to its copy operations make
it easy to inadvertently damage an auto_ptr via a const reference,
and because the non-owning pointer left behind by a copy is an
open invitation to dangling references.  The auto_ptr& arguments
to the copy constructor and assignment operator were not const in
the CD-1 auto_ptr, but were made const to allow auto_ptr values to
be passed to and returned from functions.  The C++ language now
allows a more effective solution.

We propose to restore the CD-1 auto_ptr semantics by:
-    removing const from the arguments to all copy operations and
     from the release() function;
-    restoring the pointer-zeroing effect of release();
-    restoring the reset() function; and
-    adding conversion functions and a private auxiliary class to
     allow auto_ptr rvalues to convert to lvalues.
Draft text to replace 20.4.5 follows.

     20.4.5 Template class auto_ptr

1    Template auto_ptr holds a pointer to an object obtained via
     new and deletes that object when it itself is destroyed (such
     as when leaving block scope 6.7).

2    Template auto_ptr_ref holds a reference to an auto_ptr. It is
     used by the auto_ptr conversions to allow auto_ptr objects to
     be passed to and returned from functions.

     namespace std {
       template<class X> class auto_ptr {
          template<class Y> struct auto_ptr_ref {};
       public:
         typedef X element_type;

       // 20.4.5.1 construct/copy/destroy:
         explicit auto_ptr(X* p=0) throw();
         auto_ptr(auto_ptr&) throw();
         template<class Y> auto_ptr(auto_ptr<Y>&) throw();
         auto_ptr& operator=(auto_ptr&) throw()
         template<class Y> auto_ptr& operator=(auto_ptr<Y>&) throw();
         ~auto_ptr() throw();

       // 20.4.5.2 members:
         X& operator*() const throw();
         X* operator->() const throw();
         X* get() const throw();
         X* release() throw();
         void reset(X* p=0) throw();

       // 20.4.5.3 conversions:
         auto_ptr(auto_ptr_ref<X>) throw();
         template<class Y> operator auto_ptr_ref <Y>() throw();
         template<class Y> operator auto_ptr<Y>() throw();
       };
     }

3    The auto_ptr provides a semantics of strict ownership. An
     auto_ptr owns the object it holds a pointer to. Copying an
     auto_ptr copies the pointer and transfers ownership to the
     destination. If more than one auto_ptr owns the same object
     at the same time the behavior of the program is undefined.

      20.4.5.1 auto_ptr constructors

          explicit auto_ptr(X* p =0) throw();

1    Postconditions:  *this holds the pointer p.

          auto_ptr(auto_ptr& a) throw();

2    Effects:  Calls a.release().
3    Postconditions:  *this holds the pointer returned from
       a.release().

          template<class Y> auto_ptr(auto_ptr<Y>& a) throw();

4    Requires:  Y* can be implicitly converted to X*.
5    Effects:  Calls a.release().
6    Postconditions:  *this holds the pointer returned from
       a.release().

          auto_ptr& operator=(auto_ptr& a) throw();

7    Requires:  The expression delete get() is well formed.
8    Effects:  reset(a.release()).
9    Returns:  *this.

          template<class Y> auto_ptr& operator=(auto_ptr<Y>& a) throw();

10   Requires:  Y* can be implicitly converted to X*. The
       expression delete get() is well formed.
11   Effects:  reset(a.release()).
12   Returns:  *this.

          ~auto_ptr() throw();

13   Requires:  The expression delete get() is well formed.
14   Effects:  delete get().

     20.4.5.2 auto_ptr members

          X& operator*() const throw();

1    Requires:  get() != 0
2    Returns:  *get()

          X* operator->() const throw();

3    Requires:  get() != 0
4    Returns:  get()

          X* get() const throw();

5    Returns:  The pointer *this holds.

          X* release() throw();

6    Returns:  get()
7    Postconditions:  *this holds the null pointer.

          void reset(X* p=0) throw();

8    Effects:  If get() != p then delete get().
9    Postconditions:  *this holds the pointer p.

     20.4.5.3 auto_ptr conversions

         auto_ptr(auto_ptr_ref<X> r) throw();

1    Effects:  Calls p.release() for the auto_ptr p that r holds.
2    Postconditions:  *this holds the pointer returned from
       release().

         template<class Y> operator auto_ptr_ref <Y>() throw();

3    Returns:  An auto_ptr_ref<Y> that holds *this.

         template<class Y> operator auto_ptr<Y>() throw();

4    Effects:  Calls release().
5    Returns:  An auto_ptr<Y> that holds the pointer returned from
     release().


Analysis of Conversion operations

There are four cases to consider: direct-initialization and copy-
initialization (8.5/14) for both same-type initialization and base-
from-derived initialization.

(1) Direct-initialization, same type, e.g.

          auto_ptr<int> source();

          auto_ptr<int> p( source() );

  This is considered a direct call to a constructor of
  auto_ptr<int>,using overload resolution.  There is only one
  viable constructor:

         auto_ptr<int>::auto_ptr(auto_ptr_ref<int>)

  which is callable using the conversion

         auto_ptr<int>::operator auto_ptr_ref<int>()

  which should be selected when operator overloading tries to
  convert type auto_ptr<int> to auto_ptr_ref<int>.

  Overload resolution succeeds.  No additional copying is allowed,
  so the copy constructor need not be callable.

(2) Copy-initialization, same type, e.g.

          auto_ptr<int> source();
          void sink( auto_ptr<int> );

          main() {
              sink( source() );
          }

  According to 8.5/14:

     If the initialization is direct-initialization, or if it is
     copy-initialization where the cv-unqualified version of the
     source type is the same class as, or a derived class of, the
     class of the destination, constructors are considered...

  So this case is handled the same as the direct-initialization
  case.

(3) Direct-initialization, base-from-derived, e.g.

          struct Base {};
          struct Derived : Base {};
          auto_ptr<Derived> source();

          auto_ptr<Base> p( source() );

  This is similar to (1); in this case, the viable constructor is:

         auto_ptr<Base>::auto_ptr(auto_ptr_ref<Base>)

  which is callable using the conversion

         auto_ptr<Derived>::operator auto_ptr_ref<Base>()

  which should be selected when operator overloading tries to
  convert type auto_ptr<Derived> to auto_ptr_ref<Base>.

  Overload resolution succeeds.  No additional copying is allowed,
  so the copy constructor need not be callable.

(4) Copy-initialization, base-from-derived, e.g.

          struct Base {};
          struct Derived : Base {};
          auto_ptr<Derived> source();
          void sink( auto_ptr<Base> );

          main() {
              sink( source() );
          }

  This case is not similar to (2), because the sentence quoted
  above from 8.5/14 does not apply. So there must be a conversion
  function (operator or constructor) from the argument type to the
  parameter type, and it will be used to initialize a temporary
  variable.  Note that this initialization process does not
  involve use of a copy constructor:

  The user-defined conversion so selected is called to convert the
  initializer expression into a temporary, whose type is the type
  returned by the call of the user-defined conversion function,
  with the cv-qualifiers of the destination type.

  The parameter type is auto_ptr<Base>, so there must be a
  conversion from auto_ptr<Derived> to auto_ptr<Base>. The
  constructor

          auto_ptr<Base>::auto_ptr<Derived>(auto_ptr<Derived> &)

  does not work because the argument is an rvalue.  But the
  conversion function

          auto_ptr<Derived>::operator auto_ptr<Base>()

  does work.  The result of calling this conversion function is a
  temporary - no copy constructor is needed.

  Once the temporary has been created, the draft says:

     The object being initialized is then direct-initialized from
     the temporary according to the rules above.

  This direct-initialization is case (1) which works.

At no time in any of these four cases is the implementation
allowed to make an unnecessary copy of an auto_ptr object.
Therefore it does not matter that the copy constructor does not
work on rvalues.
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: herbs@cntc.com (Herb Sutter)
Date: 1997/12/17
Raw View
"greg" <dont@spam.me> wrote:
>> I have noticed that the definition of auto_ptr seems to have undergone an
>> about face again in the approved standard. I hope this will mean that
>> unexpected lost of ownership (through programming erros) will result in
>> clear and immediate errors (dereferencing of null pointers) in most
>systems.
>
>Yes.

...and, because of magic involving the copy ctor's taking a non-const
reference, a lot of unsafe usage is intended to be disallowed (e.g.,
vector< auto_ptr<T> >).

By "intended to be disallowed" I mean that, though I suppose you could
deliberately set out to write a wrongheaded but conforming implementation
of vector<> that would still allow this, it would be hard.

>> Could someone point me in the direction of some more detail on the
>standard
>> auto_ptr? ...

See GotW #25 (www.peerdirect.com/resources/gotw025a.html#Solution) for a
detailed discussion, posted when the change was adopted.
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: smithj@NGC.COM (Jason D. Smith)
Date: 1996/09/20
Raw View
"Philip Gruebele" <philipg@bayarea.net> wrote:

= auto_ptr seems to be a good way to automatically deallocate
= objects/structs/enums which are allocated using operator new().  However,
= it will not work with arrays of simple type (char etc.) because of the
= operator ->().

No, the existence of the code in the release mechanism prevents you from
using it for simple arrays (i.e., delete vs. delete[]).

If you really do want to manage arrays of simple types, consider using
STL's vector template

Jason.
------------------------------------------------------------------------
Jason D. Smith |       I'm not young enough to know everything.        |
smithj@ngc.com |                                                       |
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: "Philip Gruebele" <philipg@bayarea.net>
Date: 1996/09/17
Raw View
auto_ptr seems to be a good way to automatically deallocate
objects/structs/enums which are allocated using operator new().  However,
it will not work with arrays of simple type (char etc.) because of the
operator ->().  The existence of this operator disallows me from using
auto_ptr to hold something like an array of bytes.  This seems to be sort
of a half-baked solution to a common problem.

Would it not make sense to have a type like auto_ptr which does not have an
operator ->() an can be used with simple types?

Regards

Philip Gruebele



[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Matt Austern <austern@isolde.mti.sgi.com>
Date: 1996/09/17
Raw View
"Philip Gruebele" <philipg@bayarea.net> writes:

> auto_ptr seems to be a good way to automatically deallocate
> objects/structs/enums which are allocated using operator new().  However,
> it will not work with arrays of simple type (char etc.) because of the
> operator ->().  The existence of this operator disallows me from using
> auto_ptr to hold something like an array of bytes.  This seems to be sort
> of a half-baked solution to a common problem.

The operator-> isn't a problem: the draft says that it's only
instantiated if it's used.

The real reason auto_ptr can't be used to manage an array of bytes
is that it can't be used to manage an array of anything: it uses
delete, rather than delete[].  If you need to manage arrays then
you need a different solution.


[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: kanze@lts.sel.alcatel.de (James Kanze US/ESC 60/3/141 #40763)
Date: 1995/06/08
Raw View
In article <D9sqGJ.Fnw@tigadmin.ml.com> mansionj@gstldn9.merrill
(James Mansion LADS LDN X4923) writes:

|> It seems to me slightly odd that the reset method does not destroy
|> the existing object managed by the auto_ptr.

I think that the reset method does destroy the existing object, at
least in the implementations I have seen.

The wording in my version of the draft is so garbled, I cannot make
out what any of the functions are supposed to do.  But if I understand
auto_ptr correctly: reset destroys the existing object, release simply
gives up ownership.

Thus, in assignment: reset is used on the target (destination) object.
Since it is the owner, it should destroy the object.  But release is
used on the source object; since ownership is being transfered, the
object should not be destroyed.
--
James Kanze         Tel.: (+33) 88 14 49 00        email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs-Bourgeois, F-67000 Strasbourg, France
Conseils en informatique industrielle --
                              -- Beratung in industrieller Datenverarbeitung







Author: swf@ElSegundoCA.ATTGIS.COM (Stan Friesen)
Date: 1995/06/08
Raw View
In article <D9sqGJ.Fnw@tigadmin.ml.com>, mansionj@gstldn9.merrill (James Mansion LADS LDN X4923) writes:
|> It seems to me slightly odd that the reset method does not destroy
|> the existing object managed by the auto_ptr.
|>
|> On its own, I would not worry, but I am wary of leaks introduced
|> by the assignment operator.

*That* isn't a problem.  Do a flow analysis; all assignments and copies
leave the pointed to object owned by *exactly* one aut_ptr<>.

The only danger point is if a user explicitly calls reset() or release()
and does not take over management of the object.
[Hmm, should reset() and relaese() be protected or something?]

|> Is the implied behaviour on assignment intended?

Yes.  It gives away ownership to the target of the assignment.
This is necessary to avoid multiple deletes of the same object.

Auto_ptr<> is deliberately designed to avoid reference counting,
so it is about as cheap as a standard pointer.  In fact ALL of the
required functions can be made inline.





Author: swf@elsegundoca.ncr.com (Stan Friesen)
Date: 1995/06/08
Raw View
In article <D9sqGJ.Fnw@tigadmin.ml.com>, mansionj@gstldn9.merrill (James Mansion LADS LDN X4923) writes:
|> It seems to me slightly odd that the reset method does not destroy
|> the existing object managed by the auto_ptr.
|>
|> On its own, I would not worry, but I am wary of leaks introduced
|> by the assignment operator.

*That* isn't a problem.  Do a flow analysis; all assignments and copies
leave the pointed to object owned by *exactly* one aut_ptr<>.

The only danger point is if a user explicitly calls reset() or release()
and does not take over management of the object.
[Hmm, should reset() and relaese() be protected or something?]

|> Is the implied behaviour on assignment intended?

Yes.  It gives away ownership to the target of the assignment.
This is necessary to avoid multiple deletes of the same object.

Auto_ptr<> is deliberately designed to avoid reference counting,
so it is about as cheap as a standard pointer.  In fact ALL of the
required functions can be made inline.

--
swf@elsegundoca.attgis.com  sarima@netcom.com

The peace of God be with you.





Author: mansionj@gstldn9.merrill (James Mansion LADS LDN X4923)
Date: 1995/06/07
Raw View
It seems to me slightly odd that the reset method does not destroy
the existing object managed by the auto_ptr.

On its own, I would not worry, but I am wary of leaks introduced
by the assignment operator.

Is the implied behaviour on assignment intended?

Clearly, we need a way to tell an auto_ptr that the object it has is no
longer owned by it: reset appears to perform this task.  But there is no way
to get it to trash its object and reset itself except to destroy it.

James