Click here to Skip to main content
Click here to Skip to main content

Container of auto_ptr

, 14 Oct 2003 CPOL
Rate this:
Please Sign up or sign in to vote.
This article describes how auto_ptr can be used to solve a few issues.

Introduction

It is an interesting question to confuse someone that how we can make an array which has different data types or more appropriately array of objects of different classes. The answer of some clever programmer is to make one base class of all those different classes and make array of pointer of that base class, then create the appropriate object and store its address in base class pointer in array. And may be a more smart programmer suggests to make vector of base class pointer instead of array. Before going to create this, take a look at Scott Meyers's advice in "Effective STL" item 7, i.e. "When using containers of newed pointers, remember to delete the pointers before the containers is destroyed" [MEY01].

Ok you agree to delete all elements, whose pointers are stored in container, by using simple loop or making predicate and using for_each. But there is still one problem you have to keep in your mind that the destructor of your base class has to be "Virtual" because if you never do this, then the destructor of drive class won't be called. Well if you have decided to make virtual destructor in base class, then your code to do all this is something like this:

    std::vector<Base*> vecBase;
    // initialize it with appropriate drive class object
    // now delete all new object
    for (std::vector<Base*>::iterator iter_ = 
        vecBase.begin(); 
        iter_ != vecBase.end();
        ++iter_
    {
        delete *iter_;
    }

Even if you decide to make virtual destructor of your base class then there is still a case in which this solution is not good and that is point to STL container classes such as string. Because no STL classes have virtual destructor therefore you can't apply the same thing with STL container. This code clearly has resource leak if you inherit the class from std::string and store its address, even if you delete all elements.

    std::vector<std::string*> vecString;

Ok we agree to make virtual destructor and not using the pointer to container of STL container classes. But there is still one problem in this solution and that is exception safety. Suppose due to any reason, exception is thrown during the deletion loop or before deletion loop, then all elements are not deleted. The smartest solution, which comes in mind in case of dynamically created objects and exception safety, is smart pointer i.e. auto_ptr. So the solution is container of auto_ptr (COAP), but wait COAP is not a portable solution and this code shouldn't compile. Before discussing it in detail, lets take a quick review of auto_ptr first.

What is auto_ptr? Before discussing what is auto_ptr, take a look at the problem which auto_ptr solves? Take a look at this simple piece of code in which we allocate some object and do some processing on it before deleting it.

    int* pInt = new int;
    // do some work on pInt
    delete pInt;

Well the code is quite straight forward and doesn't have any problem in normal flow. But what happens if exception will be thrown before deleting the object? It is clearly resource leak. From here auto_ptr comes in action. It is just a template class which allocates object, gives pointer like interface and clear the allocated object in its destructor. Now our code becomes something like this:

    std::auto_ptr<int> ptInt(new int);
    // do work on ptInt and no need to call delete;

Now there is no need to call delete, because smart pointer is responsible to do it when it goes out of scope, whether the flow of code is normal or exception has been thrown. Item 68 of C++ Gotchas "Improper Use of auto_ptr" [DEW02] discusses this issue too as a common C++ Gotchas. The most common misuse of auto_ptr is to allocate array of objects rather than just one.

    std::auto_ptr<int> ptIntArr (new int[iLen]);

The best alternate solution is to use vector instead of dynamically allocated array itself. But if you are still interested to use auto_ptr, then take a look at adapter pattern technique discussed in Item 29 of More Exceptional C++ [SUT01], "Using auto_ptr".

So what's wrong with auto_ptr? auto_ptr holds the ownership of the object, which pointers it holds. But auto_ptr has ownership transfer semantic when you copy it. In other words when you copy auto_ptr then you will automatically transfer the ownership of the object from source to target and source auto_ptr becomes NULL. This is a reason why copy constructor and assignment operator of auto_ptr doesn't have const reference of same object, just like other copy constructors and assignment operators.

    template<typename X>
    class auto_ptr
    {
        explicit auto_ptr(X* p = 0) throw();

        // don't not have const reference as parameter
        auto_ptr (auto_ptr&) throw();
        auto_ptr& operator = (auto_ptr&) throw();

        // template version of copy constructor 
        // and assignment operator

        // other functions
    }

But what's the need of this semantic? Just suppose for a moment that auto_ptr doesn't have this semantic and after copy both source and target holds the same object, then take a look at the following code:

    void f()
    {
        auto_ptr<int> ptInt1(new Int);
        // copy constructor
        auto_ptr<int> ptInt2 (pInt1);
        auto_ptr<int> ptInt3;
        // assignment operator
        ptInt3 = pInt2;
    }

Now if both source and target holds the same objects, then when function's finished and pInt1, pInt2 and pInt3 goes out of scope, destructor of all objects called. And each destructor, except the first one, tries to delete the same object, i.e. already deleted object. But fortunately auto_ptr has transfer ownership semantic, therefore in this example ptInt1 and ptInt2 are NULL and it is safe to delete NULL. In other words it is not true copy in case of auto_ptr, i.e. source and objects are not same after copy operation. If you don't want to change the ownership of auto_ptr then make it constant, but of course there are other limitations of constants too, for further information take a look at Item 37 "auto_ptr" of Exceptional C++ [SUT00].

Now come to STL container. All STL containers have copy semantic not reference semantic, means when you insert anything in any STL container then its copy is created and put in the container and the same thing apply when you get something from container. For further information about copy semantic, take a look at Item 3 of Effective STL [MEY01]. But unfortunately the auto_ptr semantic doesn't fulfill the copy requirement of STL container, therefore it is not recommended to use it in container. If you try to do it then you may get unpredictable result, such as some or all of your value of container becomes NULL due to ownership transfer semantic, because we don't know in advance what is the internal working of a particular algorithm.

References

  1. [DEW02] C++ Gotchas, Avoiding Common Problems in Coding and Design Stephen C. Dewhurst, 2002
  2. [MEY01] Effective STL Scott Meyers, 2001
  3. [SUT00] Exceptional C++ 47 Engineering puzzles, programming problems and solutions Herb Sutter, 2000
  4. [SUT01] More Exceptional C++ 40 New Engineering puzzles, programming problems and solutions Herb Sutter, 2001

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Zeeshan Amjad
Software Developer (Senior) Bloomberg LP
United States United States
Working as a Sr C++ Developer at Bloomberg LP

Comments and Discussions

 
Questionwhy it does not work? PinmemberJakub Piwowarczyk16-Mar-10 4:35 
GeneralItem 8. Never create containers of auto_ptrs Pinmembergabegabe21-May-09 21:53 
QuestionSo your article says "don't use auto_ptr in std containers"? Pinmemberpeterchen26-Mar-08 21:23 
Generalcontainer of auto_ptr PinmemberSHAVIT22-Oct-03 0:16 
QuestionDoes some pointer provides memory-check for operation correctness control ? Pinmembervgrigor21-Oct-03 1:13 
GeneralUse a better smart pointer! Pinmemberjhwurmbach15-Oct-03 6:51 
GeneralRe: Use a better smart pointer! PinmemberZeeshan Amjad15-Oct-03 19:47 
GeneralRe: Use a better smart pointer! Pinmemberemilio_g16-Oct-03 1:18 
GeneralRe: Use a better smart pointer! Pinmemberjhwurmbach16-Oct-03 2:59 
GeneralRe: Use a better smart pointer! Pinmemberemilio_g16-Oct-03 4:40 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141216.1 | Last Updated 15 Oct 2003
Article Copyright 2003 by Zeeshan Amjad
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid