Click here to Skip to main content
15,868,016 members
Articles / Programming Languages / C++
Article

TAutoPtr<TYPE, CLEANUPOBJECT>

Rate me:
Please Sign up or sign in to vote.
3.00/5 (1 vote)
29 Aug 20014 min read 65.8K   909   17   9
Automatic resource deallocation using TAutoPtr<TYPE, CLEANUPOBJECT>

Introduction      The solution      What are the benefits?      Advanced TAutoPtr<> methods

Introduction

TAutoPtr<> template class develops the idea of AutoPtr<> published at CodeGuru 05-Jan-2000. You may find the corresponding article at http://www.codeguru.com/cpp_mfc/AutoPtr.html. That article is out-of-date now, but you may read it for better understanding the main concept. AutoPtr<> had a disadvantage viz its cleanup function used void* parameter and had to guess about the TYPE of the resource it should deallocate. The common problem (and solution) relative to void* is described in the Comments section below the mentioned article. TAutoPtr<> uses a better approach. It uses a CLEANUPOBJECT instead of old-styled AutoPtr's CLEANUPFXN.

The solution

TAutoPtr<> is designed to be used within a block of code. It stores the pointer to the object of type TYPE (the first template parameter). It is assumed that the object of type TYPE is a dynamically allocated resource, so after using this resource the programmer must call a corresponding deallocating procedure (such as delete, delete[], decrementing the object reference counter or something else). The necessity of calling such deallocating procedures leads to many additional lines of code in your project, the more lines the more branched your algorithm is. Note also you can simply forget to deallocate a resource in some branch of your algorithm :-(. So... better automate the resource deallocation. TAutoPtr<> interface emulates the behavior of plain C-style pointer, so the syntax is pretty much familiar to you. Instead of the the following code

{
    CMyClass* pMyClass = CMyClass::CreateInstancePtr();
    pMyClass->SomeMethod();
    CMyClass::ReleaseInstancePtr(pMyClass);
}

you can write

{
    TAutoPtr<CMyClass, SReleaseInstancePtr> autoMyClass( CMyClass::CreateInstancePtr() );
    autoMyClass->SomeMethod();
}

SReleaseInstancePtr is a class (or a struct, in my example S stands for 'struct') encapsulating the resource deallocation procedure. It must meet the requirements of std::unary_function<>, because TAutoPtr<> uses its CLEANUPOBJECT parameter in the std::unary_function<> manner. After leaving the scope SReleaseInstancePtr::operator()(CMyClass*) will be called inside TAutoPtr<> destructor. This call should deallocate the resource. What does it mean "to deallocate the resource" is up to the programmer. This should depend on the way you are going to receive the pointer to the resource. In my example the implementation is pretty simple:

struct SReleaseInstancePtr
{
    void operator()(CMyClass* p)
    {
        if(p)
            CMyClass::ReleaseInstancePtr(p);
    }
}

Or even simpler, if CMyClass::ReleaseInstancePtr() cares itself about processing the NULL value passed to the parameter p:

struct SReleaseInstancePtr
{
    void operator()(CMyClass* p)
    {
         CMyClass::ReleaseInstancePtr(p);
    }
}

To shorten a long TAutoPtr<> declaration you can write a typedef:

typedef TAutoPtr<CMyClass, SReleaseInstancePtr> TMyClassAutoPtr;

and then use this typedef throughout your code:

TMyClassAutoPtr autoMyClass( CMyClass::CreateInstancePtr() );

What are the benefits?

The resource is released automatically, this saves programming efforts and prevents resource leaks, especially in large progects.

The same mechanism can be used for automatic releasing heterogeneous resources (memory, files, semaphores, COM objects etc). Just implement your special CLEANUPOBJECT for your concrete resource type.

Another advantage is the CLEANUPOBJECT may be a template itself. This allows releasing different resources with a similiar deallocation interface using just a single template:

template<typename TYPE>
struct SReleaseInstancePtr
{
    void operator()(TYPE* p)
    {
        TYPE::ReleaseInstancePtr(p);
    }
};

Advanced TAutoPtr<> methods

In some cases it is necessary to explicitly "forget" to release the resource. Use the Forget() function for this. After calling Forget() the resource will NOT be destroyed after leaving the scope.

{
    TAutoPtr<CMyClass, SReleaseInstancePtr> autoMyClass( CMyClass::CreateInstancePtr() );
    autoMyClass->SomeMethod();
    autoMyClass.Forget();    // CMyClass instance pointer will NOT be released!
}

The TAutoPtr<TYPE, CLEANUPOBJECT>::m_bOwns member variable indicates whether TAutoPtr<> must deallocate the assigned resource inside the destructor. Some functions (such as ByRef(), ByPtr(), Clear()) use an additional parameter to manipulate this flag explicitly. This is rarely necessary, the default behavior is consistent, but you may try playing this flag for a very tricky coding.

Some function may return the resource pointer via a C++ reference to pointer or a pointer to pointer. To handle this use ByRef() or ByPtr() methods respectively. For example, the resource allocation function may have the following signature:

static bool CMyClass::CreateInstancePtr(CMyClass*& rpMyClass);

Suppose it returns true if the resource is allocated successfully. You can write the following code using TAutoPtr<>. Note that this code is safe (from the viewpoint of memory management) independing on whether the resource was allocated successfully or not:

{
    TAutoPtr<CMyClass, SReleaseInstancePtr> autoMyClass;
    if( CMyClass::CreateInstancePtr( autoMyClass.ByRef() ) )
    {
        autoMyClass->SomeMethod();
    }
}

Note also that the TAutoPtr<> copy constructor and the corresponding

assignment
operator
are declared private. This is correct, because copying or assigning TAutoPtr<> instances is potentially unsafe. It is not possible to write the TAutoPtr<TYPE, CLEANUPOBJECT>::operator=(const TAutoPtr<TYPE, CLEANUPOBJECT>&) suitable for all possible situations. There are pitfalls. Better avoid them.

For other details I advise you to explore the TAutoPtr<> source code and debug the sample application. Both are tiny.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Russian Federation Russian Federation
VC++, MFC, ODBC, OLEDB
Python
Perl
XML
AutoCAD R<=14.0 ObjectARX, AutoLISP

Comments and Discussions

 
Questionhandling HANDLES? Pin
4-Sep-01 14:53
suss4-Sep-01 14:53 
AnswerRe: handling HANDLES? -oops Pin
4-Sep-01 14:55
suss4-Sep-01 14:55 
GeneralRe: handling HANDLES? -oops Pin
4-Sep-01 14:56
suss4-Sep-01 14:56 
still not right, let's try this:

Line 2 is missing the greater then-less then, TAutoPtr<int> tIntHolder(new int(-197));
GeneralMinor suggestions Pin
Eric Kenslow3-Sep-01 8:42
Eric Kenslow3-Sep-01 8:42 
GeneralRe: Minor suggestions Pin
3-Sep-01 20:34
suss3-Sep-01 20:34 
GeneralLost &lt; and &gt; Pin
Thomas Freudenberg30-Aug-01 1:16
Thomas Freudenberg30-Aug-01 1:16 
GeneralFound &lt; and &lt; Pin
Chris Maunder30-Aug-01 2:29
cofounderChris Maunder30-Aug-01 2:29 
GeneralRe: Found < and < Pin
Thomas Freudenberg30-Aug-01 2:36
Thomas Freudenberg30-Aug-01 2:36 
GeneralRe: Found < and < Pin
Chris Maunder3-Sep-01 15:23
cofounderChris Maunder3-Sep-01 15:23 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.