JonHoyle.com Mirror of MacCompanion
http://www.maccompanion.com/macc/archives/January2010/Columns/AccordingtoHoyle.htm

Resources

Ixquick

Google

macCompanion

Internet

 

Bodelin Technologies - Home of the Proscope USB Digital Microscope

Bodelin Technologies - Home of the Proscope USB Digital Microscope

 

PowerMax: Sasquatch Approved!

Used Macs & Apple Computers

The Mac Store - Apple Computers in Oregon & Washington

The Mac Store - Apple Computers in Oregon & Washington

 

IrisInk - Portland & Seattle IT Consultants

IrisInk - Portland & Seattle IT Consultants

 


 

 


Visit StepHouse Networks. Broadband DSL for Apple Users



 

Consultants

Developers

Devotees

Forums

Jobs and Careers

Mac 3D

Macazines

News

Think Different

 

According to Hoyle

According to Hoyle...

C++0x Part 4: Smart Pointers

 

macCompanion

January 2010

by Jonathan Hoyle

jonhoyle@mac.com

http://www.jonhoyle.com



Three months ago, we began our series on the changes that will be coming to the C++ language.  We looked first at some of the bug fixes, general language improvements and features which made the language easier to use:


           • C++0x Part 1: What is It (and Does It Even Matter)?
           • C++0x Part 2: A Step Forward
           • C++0x Part 3: Making Coding Easier

We now turn at some of the more advanced features of the new C++.  This month, we look at smart pointers.




Smart Pointers


Smart Pointers are objects pointing to memory which are smart enough to know when to delete themselves, rather than rely upon the user to manage its deallocation.  Virtually all modern languages, such as Java and C#, manage memory in this fashion and thus avoid memory leakages and overstepping.  In these other languages, the usual procedure to allocate dynamic memory is (just as in C++) to simply call the new keyword followed by the type of the object you wish to create; however (unlike in C++), users in many other languages typically ignore deallocation, assuming that the language's garbage collector will handle it.  C++ users have no automatic garbage collector, so they must make a delete call on the object, lest memory is leaked.  Worse still, they must know when to call to delete and when to call delete [] (for arrays of ovjects being created), as unhappiness can occur if the wrong one is invoked).




auto_ptr<>


The C++98 Standard Library came with a minimally "smart" pointer object called: auto_ptr<>.  Unfortunately, auto_ptr<> has some severe limitations to it, one of the most severe being that it uses an exclusive ownership model.  That is to say, the last auto_ptr<> receiving the assignment is the sole owner of the memory holding it.  Consider the following example:


    auto_ptr<int> ptr1(new int(0));  // ptr1 has exclusive access
    auto_ptr<int> ptr2 = ptr1;       // ptr2 now has exclusive access,
                                     //     ptr1 no longer does

This is counter-intuitive, as one does not expect the source object (i.e.: the variable on the right side of the = sign) to change in such an assignment.


There are some other severe drawbacks as well.  Those wishing to simply replace their pointers in code with auto_ptr<> will find quite a few syntactic differences.


First, there is no pointer arithmetic:


    ptr1++;            // Cannot increment an auto_ptr<>
    ptr2 = ptr1 + 1;   // Cannot add to the address of an auto_ptr<>
    val = ptr2[7];     // Cannot array index into an auto_ptr<>

Next, it is limited by an explicit constructor:


    auto_ptr<int> ptr1 = new int(1);    // Constructor disallows this syntax

Finally, and perhaps worst of all, there are no array capabilities within this class.  For example, let's say you allocate an array of integers to be managed by auto_ptr<> like so:


    auto_ptr<int> ptr1(new int[1024]);  // ptr1 points to a block of int's

You would get direct access only to the first element.  Worse still, when auto_ptr<> goes out of scope, it will call delete (not delete []), causing a memory leak.


In the end, auto_ptr<> is best used only for single object allocations, and owned exclusively by a single pointer object at any one time.  As "smart" pointers go, auto_ptr<> is one of the dumbest.  For this reason, the C++ community has, by and large, rejected auto_ptr<> as a useful solution, and its use is now rather minimal.


Visit here for more on auto_ptr<>.




shared_ptr<>


The C++0x Standard Library introduces a new smarter pointer object, called: shared_ptr<>.  Its main difference over auto_ptr<> is that it uses a shared ownership model, with reference counting used to determine when the memory it holds, is ready to be be deallocated.  For example:


    // function foo() using shared_ptr<>'s
    void foo()
    {
        shared_ptr<TypeX> ptr1;                 // ptr1 is a null smart pointer

        ...                                     // other code

        // new scope
        {
            shared_ptr<TypeX> ptr2(new TypeX);  // ptr2 points to a new object
            ptr1 = ptr2;                        // ptr1 & ptr2 both own access
                                                //    to this same object
        }
        // ptr2 leaves scope, but does not deallocate the object,
        //    since it is still being pointed at by ptr1

        ...
    }
    // ptr1 leaves scope when foo() finishes, deallocating TypeX object


A shared_ptr<> can be treated as a pointer, so it can be dereferenced like *ptr1 or call methods upon the underlying data type, such as: ptr1->foo().  The following are some constructors for shared_ptr<> that make it useful for C++ development:


    explicit shared_ptr<T>(T *ptr);       // Attaching to memory
    shared_ptr<T>(T *ptr, Fcn delFcn);    // Attaching to memory, with a
                                          //   user-defined deletion function
    shared_ptr<T>(shared_ptr<T> ptr);     // Copy constructor
    shared_ptr<T>(auto_ptr<T> ptr);       // Converting from auto_ptr<>

Note that this last constructor is converting the data from an auto_ptr<> to a shared_ptr<>, making it easier for you to transition your previous code (had you been using the older auto_ptr<> type).  There are some additional utilities made available as well, such as a swap() routine and two cast functions: static_pointer_cast() and dynamic_pointer_cast().


Fortunately for Mac programmers, shared_ptr<> is part of the std::tr1:: namespace, and thus is already available to Mac users using Xcode 2.x.


Visit here for more on shared_ptr<>.




shared_array<>


Although the shared_ptr<> class has the same array limitations as auto_ptr<> has, there is a shared_array<> class that is designed specifically for array allocations.  This is annoying, as it propagates the need to distinguish between allocations of one object and allocations of more than one object.  C++ users of the past needed to know the difference so as to determine whether to call new/delete or new[]/delete[]; C++ users of the future will still need to know this so as to determine whether to use shared_ptr<> or shared_array<>.


Sadly, not all of the limitations of auto_ptr<> are solved with shared_ptr<> and shared_array<>, but it's a definite step in the right direction.  (In a future macCompanion column, we will discuss the building of a custom smart pointer class which will solve more of these issues.)


Visit here for more on shared_array<>.




Coming Up:


C++0x Part 5: Rvalue References

C++0x Part 6: Final Thoughts



To see a list of all the According to Hoyle columns, visit:  http://www.jonhoyle.com/maccompanion 

http://www.maccompanion.com/macc/archives/January2010/Columns/AccordingtoHoyle.htm