    Листинг 15.15.  PERSIST.CPP (запоминание постоянных объектов в буфере) 

    1:	#include <iostream.h> 
    2:
    3:	class TPersist { 
    4:	private: 
    5:	   int x, y; 
    6:	public: 
    7:	   TPersist(int a,  int b) { x = а;  у = b;   }              // Конструктор 
    8:	   ~TPersistO { x = 0;  у = 0;  }                             // Деструктор 
    9:	   void *operator new(size_t,  void *p) {  return p;   } 
    10:	   friend ostream& operator« (ostream &os, TPersist &p); 
    11:	}; 
    12: 
    13:	char object[sizeof(TPersist)]; 
    14: 
    15:	main() 
    16:	{ 
    17:	  TPersist *p = new(object) TPersist(10,   20); 
    18:	  cout « *p « endl; 
    19:	  cout « "Address of object == " « tobject « endl; 
    20:	  cout « "Address of *p        == " « &(*p) « endl; 
    21:	  p->TPersist::~TPersist();                                        // Непосредственный вызов деструктора 
    22:	  //    p->TPersist();                                                        // Можно в ВС++ версии 4.0;   нельзя в 3.1 
    23:	  return 0; 
    24:	} 
    25: 
    26:	ostreamS operator« (ostreamS os, TPersist &p) 
    27:	{ 
    28:	  os « "x == " « p.x « ",  у == " « p.у; 
    29:	  return os; 
    30:	}
 
    В классе TPersist оператор new перегружается необычным способом. Вместо 
того чтобы выделить память для указателя, функция перегрузки оператора просто 
возвращает указатель р типа void. В программе в строке 17 оператор new 
используется для сохранения объекта класса TPersist в глобальном буфере, 
определенном в строке 13. Выражение new(object) вызывает перегруженную 
функцию-член оператора, передавая ей адреса символьного буфера object. 
Поскольку перегруженный оператор new просто возвращает переданный ему 
указатель р, этот несколько странно выглядящий оператор в действительности 
присваивает указателю р адрес объекта, а также вызывает конструктор класса 
TPersist для инициализации нового, выделенного в буфере объекта. 
    В программе отображаются адреса символьного буфера object и объекта в 
буфере. Эти адреса идентичны, что свидетельствует о размещении объекта в 
указанном месте. 
    Неплохим упражнением будет запуск PERSIST из отладчика Turbo Debugger. 
Проследите за содержимым буфера object во время пошагового выполнения кода с 
помощью клавиши <F8>. После выполнения строки 17 вы увидите, что в глобальном 
буфере появились значения 10 и 20; это доказывает, что перегруженный опера-: 
тор new не пользовался стандартными средствами выделения памяти в куче. 
    В строке 21 вызывается деструктор класса для объекта, адресуемого р. 
Поскольку объект содержится в глобальной переменной, может возникнуть 
необходимость в вызове деструктора именно таким способом для выполнения 
действий по очистке объекта. Для невиртуальных деструкторов следует 
использовать пряводящйся в листинге оператор следующего вида: 

    p->TPersist::~TPersist();     // Непосредственный вызов деструктора 

    C++ не распознает область действия объекта, сохраненного в буфере, и не 
может вызвать деструктор класса автоматически. Опять же, будет весьма 
поучительно выполнить этот оператор из Turbo Debugger. Если вы это сделаете, 
то увидите, как встраиваемые в код операторы деструктора обнуляют данные-члены 
объекта (строки 8 и 21). 
    Для виртуальных деструкторов, даже в случае с объектами производных 
классов, можно использовать следующую форму вызова деструктора: 

    p->TPersist();	// Непосредственный вызов деструктора 

    В Borland C++3.1 подобное упрощение синтаксиса запрещено.	


    15. Передовые средства C++     397 
