Zhen Zhang
Zhen Zhang

Reputation: 1072

Difference between "destroy" "destructor" "deallocate" in std::allocator?

In C++ std::allocator, there are three methods relating to a common concept:

I want to know:

  1. How are they different from each other from the memory management perspective?
  2. when should I use this but not that?

Thank you!


Edit: More specific doubts:

I am sorry to generalize it at first, here are some points I don't understand.

  1. What does destructor do? The documentation didn't talk about whether the memory will be released automatically when the destructor is called
  2. The destroy is used to call the destructor on a object, what does the "object" here means?

Thank you again!

Upvotes: 11

Views: 9647

Answers (2)

JPX
JPX

Reputation: 93

The answer to your question lies in the relationship between the delete operation and the object destructor.

deallocate(pointer p,size_type size)

- calls "delete p";

- "delete" implicitly calls the destructor of the object at p;
   
- frees/deallocates the memory where the object pointed by p was stored

destroy(pointer p)

- calls only the destructor  ((T*)p)->~T()
- the memory at addres p will not be freed/deallocated

About destructors

  • The explicit call of a destructor is not implicitly calling delete on the object which called the destructor.
  • note: ~MyClass(){ delete this; } is not an exception because it will generate an acces violation.

Why does it makes sense to call the destructor without using delete?

  • a dinamically allocated object could have pointers to allocated objects as member variables. If you want to free that memory without removing the original object which holds the pointers you call the overriden destructor, because the default one would not do that.

    In the following example i will try to trivialize the mentioned problem.

    example:

    
    
     template < class T,class U >        
      class MyClass{
    
         private:
            T* first_pointer;
            U* second_pointer;
    
         public:
           MyClass(){                   //constructor:
               first_pointer=new T();   //allocate memory for pointer variables
               second_pointer=new U();  //with non-argument constructors T() and U()
           }
    
          ~MyClass(){                  //destructor is overriden
              delete first_pointer;    //because the default-destructor
              delete second_pointer;   //will not release the memory allocated for
         }                             //first_pointer and second_pointer
    
         void set_first(const T& val){
              first_pointer=new T(val);
    
    
        }
    
        void set_second(const U& val){
    
               second_pointer=new U(val);
    
        }
    
     };
    
     void some_function(void){
    
        MyClass *object;
    
        object=new MyClass();//for example:the allocated object  is at memory location 00123A
    
     //lets say that after some time you dont need the memory for "first_pointer" and
     //"second_pointer" but you want to keep the memory for "object".
     //so we call the destructor.
    
        object->~MyClass();//memory at addres 00123A is still reserved for our object
                           //but the first_pointer and second_pointer locations 
                           //are deallocated.
    
    
    
      //then lets say that after some time we need to set the member variables  
        object->set_first(T(...))  //arguments depend on the defined constructors    
        object->set_second(U(...)) //for T and U. Doesn't really matter in this example
    
     //after some time we dont need the object and it's parts at all
     //so we call delete on the object
    
     delete object;   //calls our destructor to release the memory pointed to 
                      //by first_pointer and second_pointer.  
                      //then it deallocates the memory at "00123A" where our object  was 
    
    
     }   
     
     

    Now back to std::allocator and destroy() vs deallocate()

    allocator is an abstraction(interface) for memory allocation. It separates allocation from destruction, deallocation from destruction.

    destroy() - "destroys" data on a memory location which makes the object not usable,but the memory is still there for use(the object can be constructed again)

    deallocate() - "deallocates" the memory location where the object was, so that the storage is not usable for constructing the object on this location again.

Upvotes: 3

πάντα ῥεῖ
πάντα ῥεῖ

Reputation: 1

Just the brief descriptions from the cppreference.com documentation explain the differences very clearly for me

enter image description here

"1. What does destructor do? The documentation didn't talk about whether the memory will be released automatically when the destructor is called"

Any memory occupied by the std::allocator instance will be released as usual.

"2. The destroy is used to call the destructor on a object, what does the "object" here means?"

Again to cite the detailed documentation

 void destroy( pointer p ); // 1)
 template< class U >        // 2)
 void destroy( U* p );

Calls the destructor of the object pointed to by p
1) Calls ((T*)p)->~T()
2) Calls p->~U()

Object in this context means an object of type T managed by the std::allocator instance.

Upvotes: 9

Related Questions