Topic: auto_ptr: Why get() function instead of pointer cast operator?
Author: "John Hickin" <hickin@nortel.ca>
Date: 1998/07/09 Raw View
It prevents accidents. Try the following code below, has both operator T*() and
T* operator->():
template<class T>
struct X {
T* data;
X() : data( new T ) {}
operator T*() { return data; }
//operator void*() { return this; }
T* operator->() { return data; }
};
#include <iostream.h>
struct Y
{
~Y() { cout << "..toast!\n"; }
};
int main()
{
X<Y> anX;
delete anX;
}
If you add the operator void*(), however, you could have oeratorT*().
--
John D. Hickin Nortel Technology, Montreal, Quebec
(514) 765-7924 hickin@nortel.ca
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Colin Rafferty <craffert@ms.com>
Date: 1998/07/09 Raw View
John Hickin writes:
> It prevents accidents. Try the following code below, has both operator T*() and
> T* operator->():
> template<class T>
> struct X {
> T* data;
> X() : data( new T ) {}
> operator T*() { return data; }
> //operator void*() { return this; }
> T* operator->() { return data; }
> };
> #include <iostream.h>
> struct Y
> {
> ~Y() { cout << "..toast!\n"; }
> };
> int main()
> {
> X<Y> anX;
> delete anX;
> }
> If you add the operator void*(), however, you could have oeratorT*().
Even then, you couldn't have operator T*(). Imagine your sample code,
but with X::operator void*() uncommented:
void f(Y* y)
{
delete y;
}
void g()
{
X<Y> anX;
f(y); // not ambiguous, but definitely bad.
}
The implicit cast is thoroughly unambiguous, and we still have the
same problem, just a little harder to notice.
--
Colin
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Jorn Ronnow" <d97jorn.remove_this@dtek.thisgoesaway.chalmers.se>
Date: 1998/07/09 Raw View
John Hickin wrote in message <6o2jcm$dmt@bmtlh10.bnr.ca>...
>It prevents accidents.
[snip]
>int main()
>{
> X<Y> anX;
> delete anX;
>}
>
>If you add the operator void*(), however, you could have oeratorT*().
Is this really the only reason? C++ is generally free from safeguards, e.g.
the following is compilable:
void main()
{
int x;
// the programmer shoots himself in the foot, legally:
delete &x;
}
I thought there might be a situation where the compiler would be confused
(for example when resolving overloading?), but I can't think of any such
situation.
Anyway, using a private operator void*() is a good idea!
cul8r/Jorn
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "John Hickin" <hickin@nortel.ca>
Date: 1998/07/11 Raw View
> Anyway, using a private operator void*() is a good idea!
For those forwarned it may provide a little extra protection but (see Colin
Rafferty's reply) it isn't foolproof.
In general, implicit cast operators which return a pointer or reference to
private data can often lead to undesireable results. I believe that's why
basic_string has no implicit cast.
--
John D. Hickin Nortel Technology, Montreal, Quebec
(514) 765-7924 hickin@nortel.ca
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1998/07/11 Raw View
"Jorn Ronnow" <d97jorn.remove_this@dtek.thisgoesaway.chalmers.se> writes:
>Is this really the only reason? C++ is generally free from safeguards, e.g.
>the following is compilable:
>void main()
>{
> int x;
> // the programmer shoots himself in the foot, legally:
> delete &x;
>}
Let's not confuse what some compilers do with what the language
defintion says.
The draft standard says that deleting a pointer for which there
is no matching new is not valid; the results are undefined.
Some compilers might let this code go by (which they are
allowed to do). A compiler might diagnose the error at compile
time, but it is unlikely. Many current implementations provide the
option of catching the error at run time.
--
Steve Clamage, stephen.clamage@sun.com
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Bill Wade" <bill.wade@stoner.com>
Date: 1998/07/11 Raw View
Jorn Ronnow wrote in message <6o36mq$mr7$1@oden.abc.se>...
>Is this really the only reason?
One good use for auto_ptr is a return result from functions that allocate
memory:
auto_ptr<T> GiveMeAT();
L1: T* tp = GiveMeAT();
L2: tp->DoSomething(); // Undefined
L1 is not legal, but would be if operator T*() existed. Note that the
allocated memory is deleted before L2 is executed. (after the assignment the
temporary auto_ptr is destructed).
Since the compiler doesn't allow L1 as-is I must change it to one of
auto_ptr<T> tp = GiveMeAT(); // Now L2 works.
or
T* tp = GiveMeAT().get(); // I'm an idiot
or
T* tp = GiveMeAT().release(); // Some chance of being correct.
Since the original L1 doesn't have the semantics you might expect, IMO it is
a good thing that the compiler tells me to take a closer look.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: ncm@nospam.cantrip.org (Nathan Myers)
Date: 1998/07/12 Raw View
Bill Wade<bill.wade@stoner.com> wrote:
>One good use for auto_ptr is a return result from functions that allocate
>temporary auto_ptr is destructed).
>...
> auto_ptr<T> tp = GiveMeAT(); // Now L2 works.
>or
> T* tp = GiveMeAT().get(); // I'm an idiot
>or
> T* tp = GiveMeAT().release(); // Some chance of being correct.
I had advocated calling the function "leak" rather than "get",
but the working group was too weenie to go for that. :-)
--
Nathan Myers
ncm@nospam.cantrip.org http://www.cantrip.org/
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Jorn Ronnow" <d97jorn.remove_this@dtek.thisgoesaway.chalmers.se>
Date: 1998/07/09 Raw View
Below is an enhanced (?) auto_ptr, where a pointer cast operator "operator
T* ()" is added so that you don't need to call auto_ptr::get() explicitly.
Since auto_ptr is standardized, I suspect there is a good reason for not
having an "operator T* ()" in the class. What reason might that be???
cul8r
/J rn
#include <memory>
template<class T> class auto_ptr2 : public std::auto_ptr<T>
{
public:
explicit auto_ptr2 (T* p=0) : std::auto_ptr<T>(p) {}
auto_ptr2( auto_ptr2& a ) : std::auto_ptr<T>(a) {}
operator T*() const { return get(); }
};
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]