Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

std

c++11

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

  • deallocate
  • destroy
  • destructor

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!

like image 629
Zhen Zhang Avatar asked Oct 31 '14 03:10

Zhen Zhang


People also ask

Can an allocator deallocate a region of memory?

If an allocator, A, allocates a region of memory, R, then R can only be deallocated by an allocator that compares equal to A.

What is allocator in C++?

Allocators were invented by Alexander Stepanov as part of the Standard Template Library (STL). They were originally intended as a means to make the library more flexible and independent of the underlying memory model, allowing programmers to utilize custom pointer and reference types with the library.

What is scoped allocation in C++11?

Enhancements to allocators in C++11. The C++11 standard has enhanced the allocator interface to allow "scoped" allocators, so that containers with "nested" memory allocations, such as vector of strings or a map of lists of sets of user-defined types, can ensure that all memory is sourced from the container's allocator.

Why do we need stateful allocation in C++?

The 2011 revision of the C++ Standard removed the weasel words requiring that allocators of a given type always compare equal and use normal pointers. These changes make stateful allocators much more useful and allow allocators to manage out-of-process shared memory.


2 Answers

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.

like image 160
πάντα ῥεῖ Avatar answered Oct 19 '22 03:10

πάντα ῥεῖ


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. enter code here

like image 45
JPX Avatar answered Oct 19 '22 05:10

JPX