Ankur Arora
10/15/2008 7:17:00 AM
On Oct 13, 5:06 pm, Barry <dhb2...@gmail.com> wrote:
> On Oct 13, 10:10 pm, Ankur Arora <ankuraror...@gmail.com> wrote:
>
>
>
> > Thanks for the reply Kai!
> > Please see the comments below.
>
> > On Oct 13, 2:53 pm, Kai-Uwe Bux <jkherci...@gmx.net> wrote:
>
> > > Ankur Arora wrote:
> > > > Hi All,
>
> > > > I'm building a sample application that uses a custom auto_ptr
> > > > implementation.
> > > > The program crashes with the following output:-
>
> > > > Output (Debug Assertion failed)
> > > > ----------
>
> > > > release called
> > > > copy constructor
> > > > aap: ptr2= 10
> > > > aap: ptr3= 20
> > > > aap: ptr3= 10
> > > > aap: exiting app
> > > > Deleting pointee...10
> > > > Deleting pointee...-572662307 (....problem ?)
>
> > > > Code
> > > > --------
>
> > > Just a data point: your code works for me with output
>
> > > release called
> > > copy constructor
> > > aap: ptr2= 10
> > > aap: ptr3= 20
> > > Inside operator=
> > > Inside operator=, calling reset
> > > release called
> > > reset called
> > > aap: ptr3= 10
> > > aap: exiting app
> > > Deleting pointee...10
>
> > > So I just have nits:
>
> > > > #include<iostream>
>
> > > > using namespace std;
>
> > > It's a bad idea to use using namespace std in a header.
>
> > Agreed!
>
> > > [snip]
>
> > > > template <class T>
> > > > inline MyAutoPtr<T>::~MyAutoPtr()
> > > > {
> > > > if(pointee)
> > > > {
> > > > cout<<"\n\t Deleting pointee..."<<*pointee;
> > > > delete pointee;
> > > > }
> > > > }
>
> > > delete will perform its own check for 0. It is required to be a null-op in
> > > that case.
>
> > I did this since removing this check caused the program to crash, even
> > though I had made pointee equals to 0 in release(), which was used in
> > the copy constructor.
> > I'm using visual studio 2008 express edition. You reckon this is a
> > complier issue?
>
> > > [snip]
>
> > > > template<class T>
> > > > template<class U>
> > > > MyAutoPtr<T>& MyAutoPtr<T>::operator=(MyAutoPtr<U>& rhs)
> > > > {
> > > > cout<<"\n\t Inside operator=";
> > > > if(this!=&rhs)
>
> > > This if-clause will not compile when T and U are different.
>
> > > You could use
>
> > > if ( this->pointee == rhs.pointee )
>
> > > instead (I think).
>
> > I saw this example in "More Effective C++" by scott meyers. This was
> > how its used in that book. Here is a code.
>
> > //Interface
> > template<class T>
> > class auto_ptr {
> > public:
> > explicit auto_ptr(T *p = 0); // see Item 5 for a
> > // description of
> > "explicit"
> > template<class U> // copy constructor member
> > auto_ptr(auto_ptr<U>& rhs); // template (see Item 28):
> > // initialize a new
> > auto_ptr
> > // with any compatible
> > // auto_ptr
> > ~auto_ptr();
> > template<class U> // assignment operator
> > auto_ptr<T>& // member template (see
> > operator=(auto_ptr<U>& rhs); // Item 28): assign from
> > any
> > // compatible auto_ptr
> > T& operator*() const; // see Item 28
> > T* operator->() const; // see Item 28
> > T* get() const; // return value of current
> > // dumb pointer
> > T* release(); // relinquish ownership of
> > // current dumb pointer
> > and
> > // return its value
> > void reset(T *p = 0); // delete owned pointer;
> > // assume ownership of p
> > private:
> > T *pointee;
> > template<class U> // make all auto_ptr
> > classes
> > friend class auto_ptr<U>; // friends of one another
>
> > };
>
> > //Implementation
> > template<class T>
> > inline auto_ptr<T>::auto_ptr(T *p)
> > : pointee(p)
> > {}
> > template<class T>
> > inline auto_ptr<T>::auto_ptr(auto_ptr<U>& rhs)
> > : pointee(rhs.release())
> > {}
> > template<class T>
> > inline auto_ptr<T>::~auto_ptr()
> > { delete pointee; }
> > template<class T>
> > template<class U>
> > inline auto_ptr<T>& auto_ptr<T>::operator=(auto_ptr<U>& rhs)
> > {
> > if (this != &rhs) reset(rhs.release());
> > return *this;
> > }
> > template<class T>
> > inline T& auto_ptr<T>::operator*() const
> > { return *pointee; }
> > template<class T>
> > inline T* auto_ptr<T>::operator->() const
> > { return pointee; }
> > template<class T>
> > inline T* auto_ptr<T>::get() const
> > { return pointee; }
> > template<class T>
> > inline T* auto_ptr<T>::release()
> > {
> > T *oldPointee = pointee;
> > pointee = 0;
> > return oldPointee;}
>
> > template<class T>
> > inline void auto_ptr<T>::reset(T *p)
> > {
> > if (pointee != p) {
> > delete pointee;
> > pointee = p;
> > }
>
> > }
>
> > Anything wrong with the above ? (would be surprised if there is, as it
> > came from scott meyers)
>
> > > > Q1. Any problems with the above code ?
>
> There's a reversion for auto_ptr (IIRC, a article is proviede by Mayer
> on
> this), adding auto_ptr_ref for conversion, which supports rvalue
> initialization for auto_ptr. which is done transparently.
>
> void fun(auto_ptr<T> ptr);
> fun(auto_ptr(new T)); // rvalue -> auto_ptr_ref -> auto_ptr
>
>
>
> > > It works with g++.
>
> > Again, looks like an issue with visual studio 2008 express.
>
> there are two problem with visual C++ 2005 in this issue:
> 1. as extension, "explicit" does NOT work as standard says.
> needs /Za switch to turn it off.
>
> 2. auto_ptr_ref use void* rather T*
>
> point 2 is fixed by VS 2008(none expression version,
> but I expression version should ship the same lib)
>
>
>
> > > > Q2. What is causing operator= not to be called and how to fix it ?
>
> > > A bug in your compiler?
>
> > > [snip]
>
> --
> Best Regards
> Barry
Thanks Barry.