Re: Destructor for const object

From: Nick Hounsome (nh002_at_blueyonder.co.uk)
Date: 04/14/04

  • Next message: Buster: "Re: CX-Post: hello world"
    Date: Wed, 14 Apr 2004 08:28:28 +0100
    
    

    "Virendra Verma" <virenbeena@hotmail.com> wrote in message
    news:30ee7e04.0404131108.1df58d18@posting.google.com...
    > Thanks both of you.
    >
    > I believe I have to use a reference counted class. The problem with
    > the above scenario was that I was using class variables for DbPtr
    > class which get duplicated before returning and thus committing both
    > copies. Here is the code that does the trick. DbBasePtr class is only
    > a single copy and keeps track commit status. If the copy is already
    > committed, second commit will simply be ignored.
    >

    It is still not clear what you are trying to do but I believe that it is
    still
    totally wrong.

    1. For the DbAutoPtr you cannot have the reference count in the pointer.
    It must either be in the object pointed to or on the heap.
    2. DbAutoPtr ctor should take a T* because it is supposed to point to a T.
    3. The pointer should ONLY do the owning/commit. Use a separate mechanism to
    create new instances or find them initially in the db.
    4. The sizeof suggests an extremely dodgy implementation. I suggest that you
    should be allocating
    these things with a custom new: as in DbAutoPtr<X> xp = new(db) X;
    5. Your DbRefCount isn't a reference count. I think I see what you are
    trying to do but you can
    do this more cleanly by storing the reference count separately - the ref
    count should not be
    in the DB unless you have multiple concurrent cliemts with locking.

    > I have another question. In my DbAutoPtr<T> class below, which
    > operator gets called for the rvalue operand, a->? Is there an implicit
    > or elegant (without creating or typecasting to a const object) way of
    > "const T& operator->( ) const" version to be called as the rvalue is
    > not being modified?

    1. What's wrong with const T*?
    2. -> operates on pointers not references.

    >
    > struct C {
    > int x;
    > };
    >
    > struct A {
    > int y;
    > };
    >
    >
    > DbStore db;
    > DbAutoPtr< C> p(db, 0, sizeof( C ) );
    > DbAutoPtr< A > a( db, 0, sizeof(A) );
    >
    > p->x = a->y;
    >
    >
    > ===================
    > // DbAutPtr.h - auto pinter
    >
    > #ifndef _DBAUTPTR_H_
    > #define _DBAUTPTR_H_
    >
    > #include "syTypes.h"
    > #include "DbDefs.h"
    > #include "DbBasPtr.h"
    > #include "DbRefCnt.h"
    >
    > class DbStore;
    >
    > //////////////////////////////////////////////////////////////////////////
    > // DbAutoPtr< T > class
    > //////////////////////////////////////////////////////////////////////////
    > template< class T >
    > class DbAutoPtr {
    > public:
    > DbAutoPtr( );
    > DbAutoPtr( DbStore& rStore, fsize_type nAdr );
    > DbAutoPtr( DbStore& rStore, fsize_type nAdr, size_type nSize );
    > ~DbAutoPtr( );
    >
    > // Operators
    > T* operator->( );
    > const T* operator->( ) const;
    > DbAutoPtr< T >& operator=( const DbBasePtr& rP );
    >
    > T& operator*( );
    > const T& operator*( ) const;
    >
    > bool isNull( ) const;

    unnecessary and unnatural - it should work like an ordinary ptr

    >
    > fsize_type address( );
    > fsize_type address( ) const;
    > size_type size( ) const;
    > void setAddress( fsize_type nAdr );
    > void setSize( size_type nSize );
    > bool loadData( );
    > bool writeData( );

    All this stuff above belongs somewhere else.

    >
    > const DbBasePtr * basePtr( ) const;

    ?

    >
    > // protected:
    > const T * pointer( ) const;
    > T * pointer( );
    >
    > protected:
    > DbRefCount< DbBasePtr > _oData; // Object data

    How does this work then?

    > };
    >
    > //////////////////////////////////////////////////////////////////////////
    > template<class T>
    > inline DbAutoPtr<T>::DbAutoPtr( )
    > //////////////////////////////////////////////////////////////////////////
    > {
    > }
    >
    > //////////////////////////////////////////////////////////////////////////
    > template<class T>
    > inline DbAutoPtr<T>::DbAutoPtr( DbStore& rStore, fsize_type nAdr )
    > //////////////////////////////////////////////////////////////////////////
    > {
    > _oData = DbBasePtr( rStore, nAdr, sizeof( T ) );
    > _oData->loadData( );
    > }
    >
    > //////////////////////////////////////////////////////////////////////////
    > template<class T>
    > inline DbAutoPtr<T>::DbAutoPtr( DbStore& rStore, fsize_type nAdr,
    > size_type nSize )
    > //////////////////////////////////////////////////////////////////////////
    > {
    > _oData = DbBasePtr( rStore, nAdr, nSize );
    > _oData->loadData( );
    > }
    >
    > //////////////////////////////////////////////////////////////////////////
    > template<class T>
    > inline DbAutoPtr<T>::~DbAutoPtr( )
    > //////////////////////////////////////////////////////////////////////////
    > {
    > if( !_oData.isNull() )
    > _oData->writeData( T::Clsid() );
    > }
    >
    > //////////////////////////////////////////////////////////////////////////
    > template<class T>
    > inline DbAutoPtr< T >& DbAutoPtr<T>::operator=( const DbBasePtr& rP )
    > //////////////////////////////////////////////////////////////////////////
    > {
    > if( _oData.isNull() ) {
    > _oData = rP;
    > _oData->loadData( );
    > }
    > return *this;
    > }
    >
    > //////////////////////////////////////////////////////////////////////////
    > template<class T>
    > inline const DbBasePtr * DbAutoPtr<T>::basePtr( ) const
    > //////////////////////////////////////////////////////////////////////////
    > {
    > return _oData.pointer();
    > }
    >
    > //////////////////////////////////////////////////////////////////////////
    > template<class T>
    > inline T* DbAutoPtr<T>::pointer( )
    > //////////////////////////////////////////////////////////////////////////
    > {
    > return (T*) _oData.pointer()->dataPointer();
    > }
    >
    > //////////////////////////////////////////////////////////////////////////
    > template<class T>
    > inline const T* DbAutoPtr<T>::pointer( ) const
    > //////////////////////////////////////////////////////////////////////////
    > {
    > return (const T*) _oData.pointer()->dataPointer();
    > }
    >
    > //////////////////////////////////////////////////////////////////////////
    > template<class T>
    > inline const T* DbAutoPtr<T>::operator->() const
    > //////////////////////////////////////////////////////////////////////////
    > {
    > return (const T*) pointer( );
    > }
    >
    > //////////////////////////////////////////////////////////////////////////
    > template<class T>
    > inline T* DbAutoPtr<T>::operator->()
    > //////////////////////////////////////////////////////////////////////////
    > {
    > return (T*) pointer();
    > }
    >
    > //////////////////////////////////////////////////////////////////////////
    > template<class T>
    > inline const T& DbAutoPtr<T>::operator*() const
    > //////////////////////////////////////////////////////////////////////////
    > {
    > V_ASSERT( pointer( ) );
    > return *((const T*) pointer( ));
    > }
    >
    > //////////////////////////////////////////////////////////////////////////
    > template<class T>
    > inline T& DbAutoPtr<T>::operator*()
    > //////////////////////////////////////////////////////////////////////////
    > {
    > V_ASSERT( pointer( ) );
    > return *((T*) pointer( ));
    > }
    >
    > //////////////////////////////////////////////////////////////////////////
    > template<class T>
    > inline bool DbAutoPtr<T>::isNull( ) const
    > //////////////////////////////////////////////////////////////////////////
    > {
    > return _oData.isNull( ) || (0 == _oData->size( ) );
    > }
    >
    > //////////////////////////////////////////////////////////////////////////
    > template<class T>
    > inline fsize_type DbAutoPtr<T>::address( ) const
    > //////////////////////////////////////////////////////////////////////////
    > {
    > return _oData->address( );
    > }
    >
    > //////////////////////////////////////////////////////////////////////////
    > template<class T>
    > inline size_type DbAutoPtr<T>::size( ) const
    > //////////////////////////////////////////////////////////////////////////
    > {
    > return _oData->size( );
    > }
    >
    > //////////////////////////////////////////////////////////////////////////
    > template<class T>
    > inline fsize_type DbAutoPtr<T>::address( )
    > //////////////////////////////////////////////////////////////////////////
    > {
    > return _oData->address( T::Clsid() );
    > }
    >
    > //////////////////////////////////////////////////////////////////////////
    > template<class T>
    > inline void DbAutoPtr<T>::setAddress( fsize_type nAdr )
    > //////////////////////////////////////////////////////////////////////////
    > {
    > _oData->setAddress( nAdr );
    > }
    >
    > //////////////////////////////////////////////////////////////////////////
    > template<class T>
    > inline void DbAutoPtr<T>::setSize( size_type nSize )
    > //////////////////////////////////////////////////////////////////////////
    > {
    > _oData->setSize( nSize );
    > }
    >
    > //////////////////////////////////////////////////////////////////////////
    > template<class T>
    > inline bool DbAutoPtr<T>::loadData( )
    > //////////////////////////////////////////////////////////////////////////
    > {
    > return _oData->loadData( );
    > }
    >
    > //////////////////////////////////////////////////////////////////////////
    > template<class T>
    > inline bool DbAutoPtr<T>::writeData( )
    > //////////////////////////////////////////////////////////////////////////
    > {
    > return _oData->writeData( T::Clsid() );
    > }
    >
    > #endif
    > ==========
    > // DbRefCount.h - compact reference counted class
    >
    > #ifndef _REFCOUNT_H_
    > #define _REFCOUNT_H_
    >
    > #include <stdlib.h>
    > #include "syTypes.h"
    >
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > // DbRefCount class
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > template< class T >
    > class DbRefCount {
    > public:
    > DbRefCount( );
    > DbRefCount( const T& t );
    > DbRefCount( const DbRefCount& rPtr );
    > ~DbRefCount( );
    >
    > T* operator->( );
    > const T* operator->( ) const;
    > T& operator*( );
    > const T& operator*( ) const;
    > DbRefCount& operator=( const T& t );
    > DbRefCount& operator=( const DbRefCount& rPtr );
    > bool operator==( const DbRefCount& rPtr ) const;
    > bool isNull( ) const;
    >
    > // protected:
    > const T * pointer( ) const;
    > T * pointer( );
    > void copyFrom( const DbRefCount& rSrc);
    > void release( );
    > void * alloc( size_t nSize );
    >
    > protected:
    > int * _pPtr;
    > };
    >
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > template< class T >
    > inline DbRefCount< T >::DbRefCount( ) : _pPtr( NULLPTR )
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > {
    > }
    >
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > template< class T >
    > inline DbRefCount< T >::DbRefCount( const T& t ) : _pPtr( NULLPTR )
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > {
    > T * p = new( alloc( sizeof(T) ) ) T( t );
    > }
    >
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > template< class T >
    > inline DbRefCount< T >::DbRefCount( const DbRefCount< T >& rPtr )
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > {
    > copyFrom( rPtr );
    > }
    >
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > template< class T >
    > inline DbRefCount< T >::~DbRefCount( )
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > {
    > release( );
    > }
    >
    > //////////////////////////////////////////////////////////////////////////
    > template<class T>
    > inline const T* DbRefCount<T>::operator->() const
    > //////////////////////////////////////////////////////////////////////////
    > {
    > return pointer( );
    > }
    >
    > //////////////////////////////////////////////////////////////////////////
    > template<class T>
    > inline T* DbRefCount<T>::operator->()
    > //////////////////////////////////////////////////////////////////////////
    > {
    > return pointer( );
    > }
    >
    > //////////////////////////////////////////////////////////////////////////
    > template<class T>
    > inline const T& DbRefCount<T>::operator*() const
    > //////////////////////////////////////////////////////////////////////////
    > {
    > V_ASSERT( pointer( ) );
    > return *pointer( );
    > }
    >
    > //////////////////////////////////////////////////////////////////////////
    > template<class T>
    > inline T& DbRefCount<T>::operator*()
    > //////////////////////////////////////////////////////////////////////////
    > {
    > V_ASSERT( pointer( ) );
    > return *pointer( );
    > }
    >
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > template<class T>
    > inline const T * DbRefCount< T >::pointer( ) const
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > {
    > V_ASSERT( _pPtr );
    > return (const T *) (_pPtr + 1);
    > }
    >
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > template<class T>
    > inline T * DbRefCount< T >::pointer( )
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > {
    > return _pPtr ? (T *) (_pPtr + 1) : NULLPTR;
    > }
    >
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > template<class T>
    > inline DbRefCount< T >& DbRefCount< T >::operator =( const T& t )
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > {
    > if( NULLPTR == _pPtr )
    > new( alloc( sizeof(T) ) ) T( t );
    > return *this;
    > }
    >
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > template<class T>
    > inline DbRefCount< T >& DbRefCount< T >::operator=( const DbRefCount<
    > T >& rPtr )
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > {
    > if( &rPtr != this ) {
    > release( );
    > copyFrom( rPtr );
    > }
    > return *this;
    > }
    >
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > template<class T>
    > inline bool DbRefCount< T >::operator==( const DbRefCount< T >& rRhs )
    > const
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > {
    > return _pPtr == rRhs._pPtr;
    > }
    >
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > template<class T>
    > inline bool DbRefCount< T >::isNull( ) const
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > {
    > return _pPtr == NULLPTR;
    > }
    >
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > template<class T>
    > inline void DbRefCount< T >::release( )
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > {
    > if( _pPtr ) {
    > (*_pPtr)--;
    > if( *_pPtr == 0 ) {
    > T * tp = pointer( );
    > tp->~T( );
    > ::free( _pPtr );
    > _pPtr = NULLPTR;
    > }
    > }
    > }
    >
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > template<class T>
    > inline void DbRefCount< T >::copyFrom( const DbRefCount< T >& rSrc )
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > {
    > _pPtr = rSrc._pPtr;
    > if( _pPtr ) (*_pPtr)++;
    > }
    >
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > template<class T>
    > inline void * DbRefCount< T >::alloc( size_t nSize )
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > {
    > int * pPtr = (int *) ::realloc( _pPtr, nSize + sizeof(int) );
    > if( NULLPTR == _pPtr ) {
    > *pPtr = 1;
    > }
    > _pPtr = pPtr;
    > return _pPtr + 1;
    > }
    >
    > #endif
    > =======
    > // DbBasPtr.h
    >
    > #ifndef _DBBASPTR_H_
    > #define _DBBASPTR_H_
    >
    > #include "syTypes.h"
    > #include "DbDefs.h"
    > #include "DbObjRef.h"
    >
    > class DbStore;
    >
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > // DbBasePtr
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > class DbBasePtr : public DbObjRef {
    > public:
    > DbBasePtr( DbStore& rStore, fsize_type nAdr, size_type nSize );
    > ~DbBasePtr( );
    >
    > const void * dataPointer( ) const;
    > void * dataPointer( );
    > fsize_type address( clsid_type nClsid );
    > fsize_type address( ) const;
    >
    > // protected:
    > bool loadData( );
    > bool writeData( clsid_type nClsid );
    > void * alloc( size_type nSize );
    >
    > protected:
    > DbStore * _pStore;
    > void * _pData; // Object data
    > };
    >
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > inline DbBasePtr::DbBasePtr( DbStore& rStore, fsize_type nAdr,
    > size_type nSize )
    > : DbObjRef( nAdr, nSize ), _pStore( &rStore ),
    > _pData( NULLPTR )
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > {
    > }
    >
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > inline DbBasePtr::~DbBasePtr( )
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > {
    > }
    >
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > inline const void * DbBasePtr::dataPointer( ) const
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > {
    > return _pData;
    > }
    >
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > inline void * DbBasePtr::dataPointer( )
    >
    ////////////////////////////////////////////////////////////////////////////
    ///
    > {
    > setDirty( );
    > return _pData;
    > }
    >
    > //////////////////////////////////////////////////////////////////////////
    > inline fsize_type DbBasePtr::address( ) const
    > //////////////////////////////////////////////////////////////////////////
    > {
    > return DbObjRef::address( );
    > }
    >
    > //////////////////////////////////////////////////////////////////////////
    > inline fsize_type DbBasePtr::address( clsid_type nClsid )
    > //////////////////////////////////////////////////////////////////////////
    > {
    > writeData( nClsid );
    > return DbObjRef::address( );
    > }
    >
    > #endif


  • Next message: Buster: "Re: CX-Post: hello world"

    Relevant Pages

    • Re: using const & in function prototypes
      ... BOOL func; ... You are passing a reference to an object instead of a copy. ... passing a pointer is at best as performant as passing a DWORD, ...
      (microsoft.public.vc.language)
    • Re: Another C# critique (major rewrite!)
      ... it would be a different kind of const. ... > pointer, and the vtable to point to the Type. ... needs answering most specifically would be is a reference a literal pointer ... >>Currently I'm thinkg about security and control. ...
      (microsoft.public.dotnet.languages.csharp)
    • Re: Global Variables
      ... They only make your code harder for other programmers ... Place a 'const' qualifier if front of every variable definition ... const pointer or const reference ...
      (comp.lang.cpp)
    • Re: Pointer and reference
      ... Use references unless you must use a pointer. ... The C++ keyword const implies a variable cannot ... by reference. ... Now if foo() won't change that city's value, ...
      (comp.lang.cpp)
    • Re: [Long, historical] Re: Var* b or Var *b
      ... // Can be described as (p1 is a const pointer to T). ... // Can also be desribed as (p2 is a pointer to const T). ... // (a is a reference to an N sized array of const T). ...
      (alt.comp.lang.learn.c-cpp)