The Wayback Machine - https://web.archive.org/web/20091027213143/http://www.codeguru.com:80/cpp/cpp/algorithms/general/article.php/c10407/

CodeGuru
Earthweb Search
Login Forums Wireless Jars Gamelan Developer.com
CodeGuru Navigation
RSS Feeds

RSSAll

RSSVC++/C++

RSS.NET/C#

RSSVB

See more EarthWeb Network feeds

follow us on Twitter

Member Sign In
User ID:
Password:
Remember Me:
Forgot Password?
Not a member?
Click here for more information and to register.

jobs.internet.com

internet.commerce
Partners & Affiliates
















Home >> Visual C++ / C++ >> C++ >> Algorithms & Formulas >> General


Clone Smart Pointer (clone_ptr)
Optimal smart pointer for STL containers
Rating:

Axter (view profile)
September 1, 2005

Environment:  C++

Go to page: 1  2  Next

Introduction

The clone_ptr class is a smart pointer that can clone itself without requiring the base class to have a clone method. It can clone itself to the type pass to the constructor. The constructor for the clone_ptr is a template method, which is able to store type information for later usage when cloning the pointer.


(continued)




The clone_ptr helps solve two main problems when using abstract pointers. It helps solve problems associated with having STL containers of abstract pointers, and it helps solve problems associated with doing a deep copy of an abstract pointer.

The clone_ptr class is a good choice for use with STL containers, because the clone pointer has operator methods for assignment (equals) operator, equality operator, and greater then operator that work like concrete object operators. That means when a sort is performed on a container of clone pointers the object being pointed to is sorted, and not the pointer address. It also means that a container of abstract pointers can be copied from one container to another, or from one part of a container to another, without resulting in having the copied object pointing to the same data.

Unlike share pointers, the clone_ptr class does not share its pointer, and it's based on the idea of strict pointer ownership logic. This logic includes owning the pointer to the object from the time of its creation until its destruction.

The clone_ptr allows for automatic deep copy of abstract pointers. Without the clone_ptr, it's difficult to create a copy constructor for an object that contains an abstract pointer.

class foo
{
   AbstractClass * m_MyAbstractClassPtr;
public:
   foo(AbstractClass * abstractclassptr_)
      :m_MyAbstractClassPtr(abstractclassptr_){}

   foo(const foo& Src)
   {
      //Without a clone_ptr, there's no C++ mechanism to determine
      //how to copy the object pointed to by the abstract pointer
   }
};

The above copy constructor would be difficult to implement without the use of the clone_ptr. The common workaround solution for the above code is to add a virtual clone method to the abstract class, and then call the clone method to create a copy. With this method, every descendant class would have to create implementation for the clone method.

By using a clone_ptr class, the correct derived object is copied, without requiring the base class to have a clone method. The copy is performed through the assignment (equals) operator.

class foo
{
   clone_ptr < AbstractClass > m_MyAbstractClassPtr;
public:
   foo(const clone_ptr < AbstractClass >
       &abstractclassptr_):m_MyAbstractClassPtr(abstractclassptr_){}
      //Or
   tempalte < class T >
   foo(T* derivedtype):m_MyAbstractClassPtr(derivedtype){}
   foo(const foo& Src)
   {
      //In the following line of code, the clone pointer will copy
      //the correct derived class without the need of a clone method
      m_MyAbstractClassPtr = Src.m_MyAbstractClassPtr;
   }
};

Background

I decided to create a new smart pointer, because the common available smart pointers are not well suited for STL containers. According to IAW C++ standards, the std::auto_ptr can not be used at all with STL containers. The boost shared_ptr class does not keep ownership of its pointer, and instead shares it. That means a shared_ptr type of smart pointer would not be a good choice if you need to copy one container to another, or one part of a container to another.

One of the main logic differences between the clone_ptr class and other smart pointers like boost::shared_ptr and auto_ptr is that the clone_ptr attempts to emulate a concrete type via pointer interface, where as boost::shared_ptr and std::auto_ptr attempts to emulate a pointer. The disadvantage of emulating a pointer is that it brings in logic that is not usually beneficial, and often detrimental to the desired effect.

An example of undesirable pointer behavior is the following comparison operator:

void CompareFoo(foo* foofoo1, foo* foofoo2)
{
   if (foofo1 == foofoo2)    //Does NOT compare the foo object, and
                             //instead only compares pointer address
   {
   ............


void CompareFoo(shared_ptr < foo > foofoo1,
                shared_ptr < foo > foofoo2)
{
   if (foofo1 == foofoo2)    //Does NOT compare the foo object,
                             //and instead only compares pointer
                             //addresses
   {
   ............

Normally, in the above code, the desired logic is to test whether what one pointer is pointing to is equal in value to what the other pointer is pointing to. However, because the above code is not de-referencing the pointers, it actually compares only the addresses of the pointers.

With a clone_ptr, the comparison is made on the object being pointed to and not on the address of the pointer.

void CompareFoo(clone_ptr < foo > foofoo1,
                clone_ptr < foo > foofoo2)
{
   if (foofo1 == foofoo2)    //Does compare the foo object
   {

In a container of a smart pointer, it's rarely required no desired to make a comparison on the pointer address, and instead, it's more beneficial and practical to have the operators apply logic to the deference pointer instead of the pointer itself. That's the main reason why the clone_ptr class does not try to do a 100% pointer emulation; instead, it's more of a hybrid in which it emulates pointers where it's beneficial, but emulates concrete types when applying most comparison operators.

Another STL container problem that the clone_ptr solves is problems associated with having a container of a type that has a constant data member.

Whenever I develop a class, I like to try to make as many of the data members contant as possible. However, when I try to use my class with a vector, I then have to remove the constantness of the data members.

Example:

class ObjectWithConstantMembers
{
public:
   ObjectWithConstantMembers(const std::string &Name,
                             int Age):m_Name(Name), m_Age(Age){}
   const std::string m_Name;
   const int m_Age;
};

void DemoUsingObjWithConstantDataMembers()
{
   std::vector<ObjectWithConstantMembers> vecObj1;
   vecObj1.push_back(ObjectWithConstantMembers("David", 44));
   ............

The above code will not compile because of the constant data members. If the above code used clone_ptr, it then would be able to compile and function.

Example:

void DemoUsingObjWithConstantDataMembers()
{
   std::vector< clone_ptr < ObjectWithConstantMembers > > vecObj2;
   vecObj2.push_back(new ObjectWithConstantMembers("David", 44));
   vecObj2[0] = new ObjectWithConstantMembers("Axter", 33);
   ............

The above code works with clone_ptr because the clone_ptr assignment (equals) operator doesn't call the object's equals operator; instead, it deletes the current pointer and creates a new object via the object's copy constructor.

About the Author

I'm a top 10 ranking member in both C++ and MFC topic areas at the Experts-Exchange.

http://www.experts-exchange.com/Cplusplus

http://www.experts-exchange.com/MFC

I started programming as a hobby in 1985 on my 8-bit Atari computer. I programmed in BASIC and in assembly language until I upgraded to a 16-bit IBM compatible in 1988. In 1989, I started programming in C using Turbo C++. IMHO, Turbo C/C++ was the best compiler available to the market for many years, until VC++ 4.0 came out.

I started using MFC with VC++ 4.0 in 1996, and I developed and sold an application called GameMenu95. It had limited success, and I retired the program in 1999.

My favorite language of choice is C++. I believe it has the best combination of flexibility, speed, and type safety.

Coding is still my hobby, and I'm very fortunate in that I get paid good money to engage in my hobby!

Go to page: 1  2  Next

Downloads

  • clone_ptr.zip - Clone Pointer Source Code
  • clone_ptr_demo.zip - Clone Pointer Demo

    Tools:
    Add www.codeguru.com to your favorites
    Add www.codeguru.com to your browser search box
    IE 7 | Firefox 2.0 | Firefox 1.5.x
    Receive news via our XML/RSS feed







  • RATE THIS ARTICLE:   Excellent  Very Good  Average  Below Average  Poor  

    (You must be signed in to rank an article. Not a member? Click here to register)

    Latest Comments:
    Updates to this article - Axter (12/14/2005)

    View All Comments
    Add a Comment:
    Title:
    Comment:
    Pre-Formatted: Check this if you want the text to display with the formatting as typed (good for source code)



    (You must be signed in to comment on an article. Not a member? Click here to register)

    internet.commediabistro.comJusttechjobs.comGraphics.com

    WebMediaBrands Corporate Info

    Legal Notices, Licensing, Reprints, Permissions, Privacy Policy.
    Advertise | Newsletters | Shopping | E-mail Offers | Freelance Jobs