Topic: auto_ptr::reset and auto_ptr::operator=
Author: howlett@netcom.com (Scott Howlett)
Date: 1995/09/14 Raw View
In article <gregorDEtM0t.Hw2@netcom.com>, gregor@netcom.com (Greg Colvin) wrote:
> In article <199509111753.AA15077@xs1.xs4all.nl> veldhuis@xs4all.nl writes:
> >It seems to me that in the assignment a deep copy should be performed in
> >stead of a binary copy.
>
> That would require that the type being pointed to have a copy constructor.
> If you wish you can write b.reset(new int(*a)) instead of b = a.
>
A copy constructor will not suffice in many cases. If a contains an object
of some polymorphic class,you would need to write something akin to
b.reset(a->clone()).
I imagine that this semantic requirement is a sufficient reason for the
_standard_ auto_ptr template not to try to do fancy things like copying its
contents (although it should be easy to derive your own my_auto_ptr template
which does.
--
Scott Howlett
Storm Software, Inc.
howlett@netcom.com
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: ted@cs.brown.edu (Tony Davis)
Date: 1995/09/20 Raw View
Interesting.
In article <MATT.95Sep18131639@physics2.Berkeley.EDU> ted@cs.brown.edu (Tony Davis) writes:
> Just to clarify, you are saying that the standard will say that
> auto_ptr<T>::reset() does NOlete its pointee, correct?
^^^^^^
That should say 'NOT delete', yes?
> Tony Davis
> ted@cs.brown.edu
Tony Davis
ted@cs.brown.edu
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1995/09/22 Raw View
Greg Colvin (gregor@netcom.com) wrote:
|> What to do when this==&rhs [in operator=] is still an open issue for the committee.
Does it really need any special consideration. The semantics of
operator= are defined as:
reset( other.release() )
There is a sequence point before the call to reset, so other.release
must finish executing before reset is called.
If &other==this, there is still no problem: the pointer is first
released, and so no longer belongs to other/this when reset is called.
The net effect is a no-op.
As this follows from the normal semantics, and is a possible and
reasonable definition of the semantics for this case, why create a
special case.
While in this thread, I'd like to bring up another point which bothers
me. I'll start by quoting some earlier postings which are relevant:
Fergus Henderson (fjh@munta.cs.mu.OZ.AU) wrote:
|> Michael Cook <mcook@cognex.com> writes:
|> >I've been using auto_ptr with g++ (a 2.6 dialect). G++ generates bogus
|> >warnings for certain expressions, but compiles the code correctly.
|> >
|> >The code it complains about is this:
|> >
|> > auto_ptr<V> byValue(auto_ptr<V> a);
|> > a = byValue(b);
|> > // warning: initialization of non-const `auto_ptr<V> &' from
|> > // rvalue `auto_ptr<V>'.
|> >
|> >It doesn't quite seem to like the fact that the copy-assignment and copy-ctor
|> >operators take non-const parameters.
|> That warning is not bogus; on the contrary, the code is ill-formed,
|> and the draft standard *requires* a diagnostic.
|> (5.2.2/3 says that argument passing is treated as initialization,
|> and 8.5.3/8 says you can't initialize a non-const reference with
|> an rvalue.)
To which Michael Cook (mcook@cognex.com) responded:
|> Hmm. Interesting. That means the auto_ptr class can't be used that way.
|> That surprises me.
It not only surprises me, it bothers me profoundly. I find the
parameter declaration of auto_ptr<T>::operator= particularly
problematic. On one hand, the right hand side of assignment definitly
*is* modified; declaring it const (and casting away const in operator=
is order to implement the current semantics) would be outright lying to
the user. It is also lying to the compiler; presumably at some future
date, a compiler will take advantage of this const declaration in order
to implement some fancy optimization, which will break in the case of
casting away const.
On the other hand, using an auto_ptr as the return value of a function
would seem to be one of its principal uses. Not allowing this would
almost render auto_ptr useless.
My current solution (in my personal implementation) is to declare the
parameter of operator= const, with *big* warnings in comments at the
point of declaration that this is a lie, and to declare the pointer
member mutable, so as to tell the compiler that the const may be a lie.
Hardly what I would call ideal, but the best I've been able to come up
with til yet.
Does anyone have any other solutions, or suggestions as to what the
standard *should* say?
--
James Kanze (+33) 88 14 49 00 email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs Bourgeois, 67000 Strasbourg, France
Conseils en informatique industrielle--
--Beratung in industrieller Datenverarbeitung
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: veldhuis@xs4all.nl
Date: 1995/09/12 Raw View
:>What follows are my best guesses for the definitions of the operator=
:>and reset functions:
:>
:> template<class T>
:> class auto_ptr {
:> public:
:> void operator=(auto_ptr<T>& rhs);
:> T * reset(T *p = 0);
:> ...
:>
:> private:
:> T *pointee;
:> };
:>
:> template<class T>
:> inline void auto_ptr<T>::operator=(auto_ptr<T>& rhs)
:> { if (this != &rhs) reset(rhs.release()); }
:>
:> template<class T>
:> inline T* auto_ptr<T>::reset(T *p)
:> {
:> delete pointee;
:> return pointee = p;
:> }
:>
:>Questions:
Sorry, I have no answers for that. I do have another question/remark.
The way the auto_ptr assignment is setup does have very different semantics
from all other assignments I know in that the previous value becomes invalid
after the assignment. Assume :
auto_ptr<int> a, b;
*a = 10; // Set a to 10.
b = a; // Set b also to a (10), but deletes a in the process ?
cout << *a; // crash ??? since a is no longer valid ?
It seems to me that in the assignment a deep copy should be performed in
stead of a binary copy.
I could be wrong when auto_ptr::release() does only set a flag that its
pointer still is valid, but it is no longer the owner of the memory pointed
to. In this case however the implementation of reset would be erroneous since
that would have to test that flag also. The only correct way of implementing
this that I can think of would be to use reference counting on the
pointee.
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]