Thread: when to call auto_ptr release?

  1. #1
    Registered User
    Join Date
    May 2006
    Posts
    1,579

    when to call auto_ptr release?

    Hello everyone,


    Auto_ptr is convenient because of it saves our work and provides a framework to auto-management life cycle to reduce potential resource leak.

    But why do we sometimes need to call release method on auto_ptr to go back to the style of manual management? Remember, when we call release, we need to delete the object instance manually later.

    (here is a sample I modified from MSDN auto_ptr sample code)

    Code:
    // auto_ptr_release.cpp
    // compile with: /EHsc
    #include <memory>
    #include <iostream>
    #include <vector>
    using namespace std;
    
    class Int 
    {
    public:
       Int( int i ) 
       {
          x = i;
          cout << "Constructing " << ( void* )this << " Value: " << x << endl; 
       };
       ~Int( ) {
          cout << "Destructing " << ( void* )this << " Value: " << x << endl; 
       };
    
       int x;
    
    };
    
    int main( ) 
    {
       auto_ptr<Int> pi ( new Int( 5 ) );
       Int* pi3 = pi.release ();
       delete pi3;
    }

    thanks in advance,
    George

  2. #2
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Only two occasions I've ever used auto_ptr's release() method.

    1) I needed the contained pointer in a standard container. Since auto_ptr's cannot be stored in a container, it was necessary to store the raw pointer (and manage the lifetime of objects pointed to by elements of that container manually).

    2) Needing to have two objects able to refer to the same pointer. Copy operations with auto_ptr (eg "a = b;") effectively set the right hand side to the NULL pointer.

  3. #3
    Registered User
    Join Date
    May 2006
    Posts
    1,579
    Thanks grumpy,


    Why auto_ptr can not be stored into container?

    Quote Originally Posted by grumpy View Post
    Only two occasions I've ever used auto_ptr's release() method.

    1) I needed the contained pointer in a standard container. Since auto_ptr's cannot be stored in a container, it was necessary to store the raw pointer (and manage the lifetime of objects pointed to by elements of that container manually).

    2) Needing to have two objects able to refer to the same pointer. Copy operations with auto_ptr (eg "a = b;") effectively set the right hand side to the NULL pointer.

    regards,
    George

  4. #4
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by George2 View Post
    Why auto_ptr can not be stored into container?
    Because STL containers store everything by value, which means they make a copy of the thing you store in them.
    Now, what happens when you make a copy of an auto_ptr?
    Code:
    auto_ptr<int> a( new int );
    auto_ptr<int> b = a;
    After you copy a to b, b will hold the pointer and a will be NULL.

  5. #5
    Registered User
    Join Date
    May 2006
    Posts
    1,579
    Thanks cpjust,


    My question is answered.

    Quote Originally Posted by cpjust View Post
    Because STL containers store everything by value, which means they make a copy of the thing you store in them.
    Now, what happens when you make a copy of an auto_ptr?
    Code:
    auto_ptr<int> a( new int );
    auto_ptr<int> b = a;
    After you copy a to b, b will hold the pointer and a will be NULL.

    regards,
    George

  6. #6
    Registered User
    Join Date
    Nov 2005
    Posts
    673
    although, you can use the boost library smart pointers in STL containers. If i recall correctly it is boost::shared_ptr or boost::weak_ptr. I cant remember which.

  7. #7
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Both.

    The reason auto_ptr cannot be stored in containers is more complex than what cpjust said. But let's leave it at saying that auto_ptr does not have normal copy semantics, and that some operations on containers assume normal copy semantics.

    If you want to see an experiment, create a std::vector<std::auto_ptr<int> >, put some values in it, and then call std::sort() on the thing (use a dereferencing predicate, i.e.
    Code:
    struct deref_less
    {
      template<typename T>
      bool operator ()(const T &lhs, const T &rhs) {
        return *lhs < *rhs;
      }
    };
    ). Observe the pointers after the sort operation.

    That is, provided that your standard library isn't smart enough to prevent compilation of the thing in the first place.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  8. #8
    Registered User
    Join Date
    May 2006
    Posts
    1,579
    Hi CornedBee,


    I am trying to implement your ideas. But there is some strange compile error for the following code. Anything wrong with my code?

    1>main.cpp
    1>d:\program files\microsoft visual studio 9.0\vc\include\vector(1209) : error C2558: class 'std::auto_ptr<_Ty>' : no copy constructor available or copy constructor is declared 'explicit'
    1> with
    1> [
    1> _Ty=int
    1> ]
    1> d:\program files\microsoft visual studio 9.0\vc\include\vector(1158) : while compiling class template member function 'void std::vector<_Ty>::_Insert_n(std::_Vector_const_ite rator<_Ty,_Alloc>,unsigned int,const _Ty &)'
    1> with
    1> [
    1> _Ty=std::auto_ptr<int>,
    1> _Alloc=std::allocator<std::auto_ptr<int>>
    1> ]
    1> d:\visual studio 2008\projects\test_autoptr1\test_autoptr1\main.cpp (16) : see reference to class template instantiation 'std::vector<_Ty>' being compiled
    1> with
    1> [
    1> _Ty=std::auto_ptr<int>
    1> ]
    1>d:\program files\microsoft visual studio 9.0\vc\include\vector(1233) : error C2558: class 'std::auto_ptr<_Ty>' : no copy constructor available or copy constructor is declared 'explicit'
    1> with
    1> [
    1> _Ty=int
    1> ]

    Code:
    #include <memory>
    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    bool foosort (auto_ptr<int> lhs, auto_ptr<int> rhs)
    {
    	return *lhs < *rhs;
    }
    
    int main( ) 
    {
    	int i = 0;
    	
    	vector<auto_ptr<int>> vc;
    	for (i = 0; i < 5; i ++) // 0 1 2 3 4
    	{
    		auto_ptr<int> pi (new int(i));
    		vc.push_back (pi);
    	}
    
    	for (i = 10; i > 5; i--) // 10 9 8 7 6
    	{
    		auto_ptr<int> pi (new int(i));
    		vc.push_back (pi);
    	}
    
    	sort (vc.begin(), vc.end(), foosort);
    
    	return 0;
    }
    Quote Originally Posted by CornedBee View Post
    Both.

    The reason auto_ptr cannot be stored in containers is more complex than what cpjust said. But let's leave it at saying that auto_ptr does not have normal copy semantics, and that some operations on containers assume normal copy semantics.

    If you want to see an experiment, create a std::vector<std::auto_ptr<int> >, put some values in it, and then call std::sort() on the thing (use a dereferencing predicate, i.e.
    Code:
    struct deref_less
    {
      template<typename T>
      bool operator ()(const T &lhs, const T &rhs) {
        return *lhs < *rhs;
      }
    };
    ). Observe the pointers after the sort operation.

    That is, provided that your standard library isn't smart enough to prevent compilation of the thing in the first place.

    regards,
    George

  9. #9
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Your compiler (or library) is smart enough not to let your code compile. Be thankful.

    Firstly, std::auto_ptr's should not be stored in a std::vector as the copy semantics of an auto_ptr is not what a vector (or any other container) expects. And the push_back() method logically copies the value of its argument.

    Second, it is not a good idea to pass a std::auto_ptr by value to a function, as (again) passing by value requires a copy constructor with correct semantics. The error messages you're getting are because of that (and the fact that the C++ specifies that std::auto_ptr has a copy constructor with the "explicit" qualifier, to prevent implicit copying of auto_ptr's by value)

  10. #10
    Registered User
    Join Date
    May 2006
    Posts
    1,579
    Great grumpy!


    Could you provide more description about what is the relationship between your below comments and the compile error message. i.e. why the error message reflects your points? I feel confused about what the compiler telling me. :-)

    1>main.cpp
    1>d:\program files\microsoft visual studio 9.0\vc\include\vector(1209) : error C2558: class 'std::auto_ptr<_Ty>' : no copy constructor available or copy constructor is declared 'explicit'
    1> with
    1> [
    1> _Ty=int
    1> ]
    1> d:\program files\microsoft visual studio 9.0\vc\include\vector(1158) : while compiling class template member function 'void std::vector<_Ty>::_Insert_n(std::_Vector_const_ite rator<_Ty,_Alloc>,unsigned int,const _Ty &)'
    1> with
    1> [
    1> _Ty=std::auto_ptr<int>,
    1> _Alloc=std::allocator<std::auto_ptr<int>>
    1> ]
    1> d:\visual studio 2008\projects\test_autoptr1\test_autoptr1\main.cpp (16) : see reference to class template instantiation 'std::vector<_Ty>' being compiled
    1> with
    1> [
    1> _Ty=std::auto_ptr<int>
    1> ]
    1>d:\program files\microsoft visual studio 9.0\vc\include\vector(1233) : error C2558: class 'std::auto_ptr<_Ty>' : no copy constructor available or copy constructor is declared 'explicit'
    1> with
    1> [
    1> _Ty=int
    1> ]


    Quote Originally Posted by grumpy View Post
    Firstly, std::auto_ptr's should not be stored in a std::vector as the copy semantics of an auto_ptr is not what a vector (or any other container) expects. And the push_back() method logically copies the value of its argument.

    Second, it is not a good idea to pass a std::auto_ptr by value to a function, as (again) passing by value requires a copy constructor with correct semantics. The error messages you're getting are because of that (and the fact that the C++ specifies that std::auto_ptr has a copy constructor with the "explicit" qualifier, to prevent implicit copying of auto_ptr's by value)

    regards,
    George

  11. #11
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Did you look up the compile error on MSDN?
    http://msdn2.microsoft.com/en-us/library/7xcz0y39.aspx

    If you open the <memory> header file in Visual Studio and look at the auto_ptr class, you'll see the copy constructor is declared with the explicit keyword...

  12. #12
    Registered User
    Join Date
    May 2006
    Posts
    1,579
    Hi cpjust,


    Yes, it is explicit. Why it is not allowed in the case of putting into vector?

    Quote Originally Posted by cpjust View Post
    Did you look up the compile error on MSDN?
    http://msdn2.microsoft.com/en-us/library/7xcz0y39.aspx

    If you open the <memory> header file in Visual Studio and look at the auto_ptr class, you'll see the copy constructor is declared with the explicit keyword...

    regards,
    George

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Error C2664 - Trying to call an external Dll
    By jamez05 in forum C++ Programming
    Replies: 3
    Last Post: 08-08-2006, 06:07 AM
  2. Class won't call
    By Aalmaron in forum C++ Programming
    Replies: 3
    Last Post: 04-13-2006, 04:57 PM
  3. Iterative Tree Traversal using a stack
    By BigDaddyDrew in forum C++ Programming
    Replies: 7
    Last Post: 03-10-2003, 05:44 PM
  4. call by reference and a call by value
    By IceCold in forum C Programming
    Replies: 4
    Last Post: 09-08-2001, 05:06 PM