Click here to Skip to main content
15,894,955 members
Articles / Programming Languages / C++

TAutoPtr<TYPE, CLEANUPOBJECT>

Rate me:
Please Sign up or sign in to vote.
3.00/5 (1 vote)
29 Aug 20014 min read 66.1K   909   17  
Automatic resource deallocation using TAutoPtr<TYPE, CLEANUPOBJECT>
<!--------------------------------------------------------------------------->
<!--                        IGNORE THIS SECTION                            -->
<html>
<head>
<title>The Code Project</title>
<meta http-equiv="Content-TYPE" content="text/html; charset=iso-8859-1">
<Style>
BODY, P, TD { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10pt }
H2,H3,H4,H5 { color: #ff9900; font-weight: bold; }
H2 { font-size: 13pt; }
H3 { font-size: 12pt; }
H4 { font-size: 10pt; color: black; }
PRE { BACKGROUND-COLOR: #FBEDBB; FONT-FAMILY: "Courier New", Courier, mono;
      WHITE-SPACE: pre; }
CODE { COLOR: #990000; FONT-FAMILY: "Courier New", Courier, mono; }
</style>
</head>
<body bgcolor="#FFFFFF" color=#000000>
<!--------------------------------------------------------------------------->


<!-------------------------------     STEP 1      --------------------------->
<!--  Fill in the details (CodeProject will reformat this section for you) -->

<pre>
Title:       TAutoPtr&ltTYPE, CLEANUPOBJECT&gt
Author:      Dmitry Leonov
Email:       dmitry.leonov@mtu-net.ru
Environment: VC++ 6.0 SP3/SP4/SP5, NT 4.0/2000, Win95/98/ME; UNIX portable (may require minor changes depending on the used compiler).
Keywords:    Smart Pointer, Object Instance Management, C++ Template
Level:       Medium to Advanced
Description: Automatic resource deallocation using TAutoPtr&ltTYPE, CLEANUPOBJECT&gt
Section      Smart Pointers
SubSection   General
</pre>

<hr width=100% noshade>


<!-------------------------------     STEP 2      --------------------------->
<!--  Include download and sample image information.                       -->

<ul class=download>
<li><a href="tautoptr_src.zip">Download source code - 2 Kb</a></li>
<li><a href="tautoptr_demo.zip">Download demo project - 5 Kb</a></li>
<li><a href="tautoptr_article.zip">Download this article - 3.5 Kb</a></li>
</ul>

<!-- <p><img src="Article.gif" alt="Sample Image" width=100 height=100></p> -->


<!-------------------------------     STEP 3      --------------------------->
<!--  Add the article text. Please use simple formatting (<h2>, <p> etc)   -->

<p>
<a href="#Introduction">Introduction</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<a href="#Solution">The solution</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<a href="#Benefits">What are the benefits?</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<a href="#Methods">Advanced TAutoPtr&lt;&gt; methods</a>
</p>
<p>&nbsp;</p>

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


<h2><a name="Solution">The solution</h2>
<p>
<code>TAutoPtr&lt&gt</code> is designed to be used within a block of code. It stores the
pointer to the object of type <code>TYPE</code> (the first template parameter). It is assumed
that the object of type <code>TYPE</code> is a dynamically allocated resource, so after using
this resource the programmer must call a corresponding deallocating procedure
(such as <code>delete</code>, <code>delete[]</code>, 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. <code>TAutoPtr&lt&gt</code> interface emulates the behavior of plain C-style
pointer, so the syntax is pretty much familiar to you. Instead of the the
following code
</p>
<pre>
{
    CMyClass* pMyClass = CMyClass::CreateInstancePtr();
    pMyClass->SomeMethod();
    CMyClass::ReleaseInstancePtr(pMyClass);
}
</pre>
<p>you can write</p>
<pre>
{
    TAutoPtr&ltCMyClass, SReleaseInstancePtr&gt autoMyClass( CMyClass::CreateInstancePtr() );
    autoMyClass->SomeMethod();
}
</pre>

<p>
<code>SReleaseInstancePtr</code> is a class (or a struct, in my example S stands for
'struct') encapsulating the resource deallocation procedure. It must meet the
requirements of <code>std::unary_function&lt&gt</code>, because <code>TAutoPtr&lt&gt</code>
uses its <code>CLEANUPOBJECT</code> parameter
in the <code>std::unary_function&lt&gt</code> manner. After leaving the scope
<code>SReleaseInstancePtr::operator()(CMyClass*)</code> will be called inside <code>TAutoPtr&lt&gt</code>
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:
</p>
<pre>
struct SReleaseInstancePtr
{
    void operator()(CMyClass* p)
    {
        if(p)
            CMyClass::ReleaseInstancePtr(p);
    }
}
</pre>
<p>
Or even simpler, if <code>CMyClass::ReleaseInstancePtr()</code> cares itself about processing
the <code>NULL</code> value passed to the parameter p:
</p>
<pre>
struct SReleaseInstancePtr
{
    void operator()(CMyClass* p)
    {
         CMyClass::ReleaseInstancePtr(p);
    }
}
</pre>

<p>To shorten a long <code>TAutoPtr&lt&gt</code> declaration you can write a <code>typedef</code>:</p>
<pre>typedef TAutoPtr&ltCMyClass, SReleaseInstancePtr&gt TMyClassAutoPtr;</pre>
<p>and then use this <code>typedef</code> throughout your code:</p>
<pre>TMyClassAutoPtr autoMyClass( CMyClass::CreateInstancePtr() );</pre>

<p>&nbsp;</p>


<h2><a name="Benefits">What are the benefits?</h2>
<p>
The resource is released automatically, this saves programming efforts and
prevents resource leaks, especially in large progects.
</p>
<p>
The same mechanism can be used for automatic releasing heterogeneous resources
(memory, files, semaphores, COM objects etc). Just implement your special
<code>CLEANUPOBJECT</code> for your concrete resource type.
</p>
<p>
Another advantage is the <code>CLEANUPOBJECT</code> may be a template itself. This allows
releasing different resources with a similiar deallocation interface using just
a single template:
</p>
<pre>
template&lttypename TYPE&gt
struct SReleaseInstancePtr
{
    void operator()(TYPE* p)
    {
        TYPE::ReleaseInstancePtr(p);
    }
};
</pre>
<p>&nbsp;</p>

<h2><a name="Methods">Advanced TAutoPtr&lt&gt methods</h2>
<p>
In some cases it is necessary to explicitly "forget" to release the resource.
Use the <code>Forget()</code> function for this. After calling <code>Forget()</code> the resource will NOT
be destroyed after leaving the scope.
</p>
<pre>
{
    TAutoPtr&ltCMyClass, SReleaseInstancePtr&gt autoMyClass( CMyClass::CreateInstancePtr() );
    autoMyClass->SomeMethod();
    autoMyClass.Forget();    // CMyClass instance pointer will NOT be released!
}</pre>

<p>
The <code>TAutoPtr&ltTYPE, CLEANUPOBJECT&gt::m_bOwns</code> member variable indicates whether
<code>TAutoPtr&lt&gt</code> must deallocate the assigned resource inside the destructor.
Some functions (such as <code>ByRef()</code>, <code>ByPtr()</code>, <code>Clear()</code>)
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.
</p>

<p>
Some function may return the resource pointer via a C++ reference to pointer or
a pointer to pointer. To handle this use <code>ByRef()</code> or <code>ByPtr()</code> methods
respectively. For example, the resource allocation function may have the following signature:
</p>
<code>static bool CMyClass::CreateInstancePtr(CMyClass*& rpMyClass);</code>

<p>
Suppose it returns <code>true</code> if the resource is allocated successfully.
You can write the following code using <code>TAutoPtr&lt&gt</code>. Note that this code is safe
(from the viewpoint of memory management) independing on whether the resource
was allocated successfully or not:
</p>
<pre>
{
    TAutoPtr&ltCMyClass, SReleaseInstancePtr&gt autoMyClass;
    if( CMyClass::CreateInstancePtr( autoMyClass.ByRef() ) )
    {
        autoMyClass->SomeMethod();
    }
}</pre>

<p>
Note also that the <code>TAutoPtr&lt&gt</code> <code>copy constructor</code> and the corresponding <code>assignment
operator</code> are declared private. This is correct, because copying or assigning
<code>TAutoPtr&lt&gt</code> instances is potentially unsafe. It is not possible to write the
<code>TAutoPtr&ltTYPE, CLEANUPOBJECT&gt::operator=(const TAutoPtr&ltTYPE, CLEANUPOBJECT&gt&)</code>
suitable for all possible situations. There are pitfalls. Better avoid them.
</p>
<p>
For other details I advise you to explore the <code>TAutoPtr&lt&gt</code> source code
and debug the sample application. Both are tiny.
</p>
<p>&nbsp;</p>

<!-------------------------------    That's it!   --------------------------->
</body>
</html>

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

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