Как выделить, так и сконструировать, зачем нужны два?

Я провел некоторое исследование, но у меня все еще есть несколько вопросов, потому что вещи не кажутся ясными, есть еще одно обсуждение, которое здесь похоже, но неясно, дан один ответ, но у него репутация ноль, и единственный комментарий говорит что ответ не правильный.

Итак, во-первых, почему std::allocate есть две функции, которые, кажется, делают то же самое? deallocate а также destroy, Из того, что я читал в C++ о создании объектов за кулисами, сначала вызывается malloc, который выделяет достаточно памяти для объекта (ов), который вы хотите, затем new создает этот объект,

но это все еще оставляет вопрос: зачем нам нужно и уничтожать, и освобождать, а также распределять и конструировать? При вызове нового ключевого слова malloc сначала выполняется d, затем объект создается в этой памяти, поэтому, если об этом позаботится с новым ключевым словом, зачем нам нужны две функции (allocate и construct), почему мы не можем просто иметь функцию называется конструкция, которая вызывает новое ключевое слово

и иметь функцию destroy, которая освобождает и удаляет объект, который делает ключевое слово delete

***Редактировать*

в функции изменения размера почему мы вызываем только destroy, но не освобождаем?

а в резервной функции мы называем и уничтожить, и освободить?

обратите внимание, что это не мой код, но реализация вектора Бьярнса

Спасибо, парни

#include <iostream>

using namespace std;

template <class T,class A = allocator<T> > class Vector{

  A alloc;
  int size;
  int space;
  T *elem;

  public:
      Vector(int size)
      : size(size),elem(new T[size])
      {

        space = size;
        for(int i = 0; i < size; i++){

            elem[i] = 0;
        }
      }

      Vector(){

         size = 0;
         elem = 0;
         space = 0;

      }

      Vector(const Vector& other)
      {

        size = other.size;
        elem = new T[other.size];
        copyValues(other);
      }

      void copyValues(const Vector& other){

         for(int i = 0; i < size; i++){

            elem[i] = other.elem[i];
         }
      }

      Vector& operator=(const Vector& other){

         T *p = new T[other.size];

         for(int i = 0; i < other.size; i++){

            p[i] = other.elem[i];
         }
         delete[] elem;
         elem = p;
         size = other.size;
         return *this;
      }

      T& operator[](int i){

         return elem[i];
      }

       T operator[](int i)const{

         return elem[i];
      }

      int vectorSize(){

       return size;
      }

      void reserve(int amount){

         if(amount <= space){
            return;
         }
         T *p = alloc.allocate(amount);
         for(int i = 0; i < size; i++){

            alloc.construct(&p[i],elem[i]);
         }
          for(int i = 0; i < size; i++){

            alloc.destroy(&elem[i]);
         }

         alloc.deallocate(elem,space);

         elem = p;
         space = amount;
      }

      void resize(int newSize,T val = T()){

         reserve(newSize);
         for(int i = size; i < newSize; i++){

            alloc.construct(&elem[i],val);
         }
         for(int i = newSize; i < size; i++){

            alloc.destroy(&elem[i]);
         }
         size = newSize;
      }

      void push_back(const T& val){

           if(space == 0){

            reserve(8);
           }
           if(size == space){

            reserve(2 * space);
           }
           alloc.construct(&elem[size],val);
           size++;

      }

};

class hey{

  public:
      int a;
      int b;

      hey(){

       a = 7;
       b = 7;
      }
      hey(int x,int y){

       a = x;
       b = y;

      }
      hey(const hey& other){

       a = other.a;
       b = other.b;

      }

      hey& operator=(const hey& other){


       a = other.a;
       b = other.b;
       return (*this);
      }

};

int main()
{
   Vector<hey> sample;
   hey h(5,3);
   hey b(7,3);
   hey c(8,2);
   sample.push_back(h);
   sample.push_back(b);
   sample.push_back(c);

   sample[0].a = 9;

   for(int i = 0; i < sample.vectorSize(); i++){

      cout << sample[i].a << endl;
   }
}

1 ответ

TL;DR. Распределитель должен предоставлять две отдельные функции, allocate а также constructпотому что они делают две разные работы.

Много контейнеров (std::vector было бы очень ярким примером) выделить больше памяти, чем им нужно для хранения текущего количества элементов. Это называется резервированием памяти и используется в целях эффективности - обычно гораздо лучше выделить один большой кусок памяти, чем несколько меньших. Вот почему распределители предоставляют allocate - так что контейнеры могут захватить кусок памяти.

Позже, когда элементы добавляются в контейнер, он должен использовать эту зарезервированную память для создания элемента в нем - и это то, что construct для.

deallocate а также destruct как раз наоборот - deallocate используется, когда вектор готов освободить память, и destruct используется, чтобы уничтожить объект, но сохранить память.

Другие вопросы по тегам