Click here to Skip to main content
6,821,293 members and growing! (19,060 online)
Email Password   helpLost your password?
Languages » C / C++ Language » General     Intermediate License: The Code Project Open License (CPOL)

Container of auto_ptr

By Zeeshan Amjad

This article describes how auto_ptr can be used to solve a few issues.
VC6, Windows, Visual-Studio, STL, Dev
Posted:14 Oct 2003
Views:49,014
Bookmarked:23 times
printPrint   add Share
      Discuss Discuss   Broken Article?Report  
16 votes for this article.
Popularity: 4.74 Rating: 3.94 out of 5
2 votes, 12.5%
1
1 vote, 6.3%
2

3
7 votes, 43.8%
4
6 votes, 37.5%
5

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)

About the Author

Zeeshan Amjad


Member
Working as a C++ Developer at Bechtel Corporation.
Occupation: Software Developer (Senior)
Company: Bechtel Corporation
Location: United States United States

Other popular C / C++ Language articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 9 of 9 (Total in Forum: 9) (Refresh)FirstPrevNext
GeneralItem 8. Never create containers of auto_ptrs Pinmembergabegabe21:53 21 May '09  
GeneralSo your article says "don't use auto_ptr in std containers"? Pinsupporterpeterchen21:23 26 Mar '08  
Generalcontainer of auto_ptr PinmemberSHAVIT0:16 22 Oct '03  
GeneralDoes some pointer provides memory-check for operation correctness control ? Pinmembervgrigor1:13 21 Oct '03  
GeneralUse a better smart pointer! Pinmemberjhwurmbach6:51 15 Oct '03  
GeneralRe: Use a better smart pointer! PinmemberZeeshan Amjad19:47 15 Oct '03  
GeneralRe: Use a better smart pointer! Pinmemberemilio_g1:18 16 Oct '03  
GeneralRe: Use a better smart pointer! Pinmemberjhwurmbach2:59 16 Oct '03  
GeneralRe: Use a better smart pointer! Pinmemberemilio_g4:40 16 Oct '03  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

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

PermaLink | Privacy | Terms of Use
Last Updated: 14 Oct 2003
Editor: Smitha Vijayan
Copyright 2003 by Zeeshan Amjad
Everything else Copyright © CodeProject, 1999-2010
Web19 | Advertise on the Code Project