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