Release() and how that works...

Started by
18 comments, last by Cyelince 22 years, 1 month ago
Your Release is fine, though it''s useless without an AddRef. But yeah, that''s how you''d do it.

I wrote a smart pointer class, although I eventually decided not to bother using it. But it was this:

  template <class Type> class pointer{    public:         pointer ( )        {            m_Object = NULL;        }         pointer ( Type* Object )        {            m_Object = Object;            if( m_Object )                m_Object->AddRef( (object**)&m_Object );        }         ~pointer ( )        {            if( m_Object )                m_Object->Release( );        }         inline operator = ( Type* Object )        {            if( m_Object )                m_Object->Release( );            m_Object = Object;            if( m_Object )                m_Object->AddRef( (object**)&m_Object );        }         inline Type* operator -> ( ) const        {            return m_Object;        }         inline Type* operator () ( ) const        {            return m_Object;        }         inline operator Type* ( ) const        {            return m_Object;        }         inline bool operator == ( Type* Object ) const        {            return m_Object == Object;        }         inline bool operator != ( Type* Object ) const        {            return m_Object != Object;        }         inline operator bool ( ) const        {            return m_Object ? true : false;        }     private:         Type*       m_Object;};  


The object had to be derived from a base object that had the AddRef and Release methods. All my classes are derived from a common base class (except pointer) so I could do things like this.

It would be used like this:
  pointer<OpenGL> pGL = new OpenGL; // Create it.pGL->SetDisplayMode( 640, 480, 16 ); // Do something.pGL = NULL; // This releases the object.  


~CGameProgrammer( );

~CGameProgrammer( );Developer Image Exchange -- New Features: Upload screenshots of your games (size is unlimited) and upload the game itself (up to 10MB). Free. No registration needed.
Advertisement
CGameProgrammer, there is a problem with your assignment operator (just what I had warned about in my code)

if Object == m_Object, the fact that you call release first may cause the object to be destroyed.

// if m_Object == Object, release Object, which may be deletedif( m_Object ) m_Object->Release( ); // This line would basically be a no-opm_Object = Object;// m_Object could now be a dangling pointer... calling AddRef would segfault.if( m_Object )    m_Object->AddRef( (object**)&m_Object ); 
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Actually, it won''t, I don''t think. Unless you say pGL = pGL of course. I suppose it''s not a bad idea checking to make sure m_Object isn''t the same as Object, but since only bad programming would cause that situation to arise, I wouldn''t waste a conditional jump.

~CGameProgrammer( );

~CGameProgrammer( );Developer Image Exchange -- New Features: Upload screenshots of your games (size is unlimited) and upload the game itself (up to 10MB). Free. No registration needed.
If you wouldn''t waste that jump, why does EVERY single reference counted pointer class I''ve seen (including those in ATL) do?
---visit #directxdev on afternet <- not just for directx, despite the name
Probably because they may be used in bad programming. When making public libraries like that, you want to be extra-careful. But for your own code, you can make optimizations if you know it won''t be a problem for you.

~CGameProgrammer( );

~CGameProgrammer( );Developer Image Exchange -- New Features: Upload screenshots of your games (size is unlimited) and upload the game itself (up to 10MB). Free. No registration needed.
It is critical to ensure correctness first, then speed.
If you are working in any kind of professional situation, you don''t know who will go through your code after you.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
I agree with Fruny. In any event, it''s always better to waste a jump rather than to spend half a day debugging your program when you in fact do assign a pointer to itself. If you are extremely concerned with performance, at least put an ASSERT in there. However, I doubt that you''ll see any speed difference just because you don''t check this case.

Correctness is also why I wrap every single DX interface method I use, and check all HRESULTs. I know that DrawPrimitive doesn''t fail unless you give it a NULL pointer, but I once had a problem even with it.
---visit #directxdev on afternet <- not just for directx, despite the name
#include "atlbase.h"//#include "d3d8.h"#pragma comment( lib, "d3d8.lib" )#pragma comment( lib, "dxguid.lib" )//...CComPtr<IDirect3D8 *> pd3d;//...int WINAPI WInMain(..){  pd3d.Attach( ::Direct3D8Create(D3D_SDK_VERSION, ...) );  // no need to call release; CComPtr does that automatically  // could also have used CComQIPtr which supports QueryInterface} 


I wanna work for Microsoft!
[ GDNet Start Here | GDNet Search Tool | GDNet FAQ | MS RTFM [MSDN] | SGI STL Docs | Google! ]
Thanks to Kylotan for the idea!
Thanks everybody for all the input...even though it seems like the subject changed a bit. I will probably just use regular pointers though. Not sure...anyway, I guess it seems okay to have a method in a class delete itself like in my Release() method, as long as it''s a pointer.

Cocyen
Just make sure you allocate your classes with new.
---visit #directxdev on afternet <- not just for directx, despite the name

This topic is closed to new replies.

Advertisement