Бьерн Страуструп - Язык программирования С++. Главы 5-8
Страница 48. Указание размещения



6.7.2 Указание размещения

 По умолчанию операция new создает указанный ей объект в свободной
 памяти. Как быть, если надо разместить объект в определенном месте?
 Этого можно добиться переопределением операции размещения. Рассмотрим
 простой класс:

        class X {
           // ...
        public:
          X(int);
          // ...
        };

 Объект можно разместить в любом месте, если ввести в функцию
 размещения дополнительные параметры:

        // операция размещения в указанном месте:
        void* operator new(size_t, void* p) { return p; }

 и задав эти параметры для операции new следующим образом:

        char buffer[sizeof(X)];

        void f(int i)
        {
          X* p = new(buffer) X(i); // разместить X в buffer
          // ...
        }

 Функция operator new(), используемая операцией new, выбирается
 согласно правилам сопоставления параметров ($$R.13.2). Все
 функции operator new() должны иметь первым параметром size_t.
 Задаваемый этим параметром размер неявно передается операцией
 new.
     Определенная нами функция operator new() с задаваемым размещением
 является самой простой из функций подобного рода. Можно привести
 другой пример функции размещения, выделяющей память из некоторой
 заданной области:

        class Arena {
           // ...
           virtual void* alloc(size_t) = 0;
           virtual void free(void*) = 0;
        };

        void operator new(size_t sz, Arena* a)
        {
          return a.alloc(sz);
        }

 Теперь можно отводить память для объектов произвольных типов из
 различных областей (Arena):

        extern Arena* Persistent; // постоянная память
        extern Arena* Shared;     // разделяемая память

        void g(int i)
        {
          X* p = new(Persistent) X(i); // X в постоянной памяти
          X* q = new(Shared) X(i);     // X в разделяемой памяти
          // ...
        }

 Если мы помещаем объект в область памяти, которая непосредственно
 не управляется стандартными функциями распределения свободной
 памяти, то надо позаботиться о правильном уничтожении объекта.
 Основным средством здесь является явный вызов деструктора:

        void h(X* p)
        {
          p->~X();             // вызов деструктора
          Persistent->free(p); // освобождение памяти
        }

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

 
« Предыдущая статья   Следующая статья »