Оператор размещения new А
Существует третья форма оператора new, которая создает объект без отведения для него памяти, то есть в памяти, которая уже была выделена. Эту форму называют оператором размещения new. Программист указывает адрес области памяти, в которой размещается объект:
new (place_address) type-specifier
place_address
должен быть указателем. Такая форма (она включается заголовочным файлом <new>) позволяет программисту предварительно выделить большую область памяти, которая впоследствии будет содержать различные объекты. Например:
#include <iostream> #include <new> const int chunk = 16; class Foo { public: int val() { return _val; } FooQ(){ _val = 0; } private: int _val; }; // выделяем память, но не создаем объектов Foo char *buf = new char[ sizeof(Foo) * chunk ]; int main() { // создаем объект Foo в buf Foo *pb = new (buf) Foo; // проверим, что объект помещен в buf if ( pb.val() == 0 ) cout << "Оператор new сработал!" << endl; // здесь нельзя использовать pb delete[] buf; return 0; |
}
Результат работы программы:
Оператор new сработал!
Для оператора размещения new нет парного оператора delete: он не нужен, поскольку эта форма не выделяет память. В предыдущем примере необходимо освободить память, адресуемую указателем buf, а не pb. Это происходит в конце программы, когда буфер больше не нужен. Поскольку buf
ссылается на символьный массив, оператор delete имеет форму
delete[] buf;
При уничтожении buf
прекращают существование все объекты, созданные в нем. В нашем примере pb
больше не ссылается на существующий объект класса Foo.
Упражнение 8.5
Объясните, почему приведенные операторы new
ошибочны:
(a) const float *pf = new const float[100]; (b) double *pd = new doub1e[10] [getDim()]; (c) int (*pia2)[ 1024 ] = new int[ ][ 1024 ]; |
(d) const int *pci = new const int;
Упражнение 8.6
Как бы вы уничтожили pa?
typedef int arr[10]; |
int *pa = new arr;
Упражнение 8.7
Какие из следующих операторов delete
содержат потенциальные ошибки времени выполнения и почему:
int globalObj; char buf[1000]; void f() { int *pi = &global0bj; double *pd = 0; float *pf = new float(O); int *pa = new(buf)int[20]; delete pi; // (a) delete pd; // (b) delete pf; // (c) de1ete[] pa; // (d) |
Упражнение 8.8
Какие из данных объявлений auto_ptr
неверны или грозят ошибками времени выполнения? Объясните каждый случай.
int ix = 1024; int *pi = & ix; int *pi2 = new int ( 2048 ); (a) auto_ptr<int> p0(ix); (b) auto_ptr<int> pl(pi); (c) auto_ptr<int> p2(pi2); (d) auto_ptr<int> p3(&ix); (e) auto_ptr<int> p4(new int(2048)); (f) auto_ptr<int> p5(p2.get()); (9) auto_ptr<int> p6(p2.release()); |
Упражнение 8.9
Объясните разницу между следующими инструкциями:
int *pi0 = p2.get(); |
Для каких случаев более приемлем тот или иной вызов?
Упражнение 8.10
Пусть мы имеем:
auto_ptr< string > ps( new string( "Daniel" ) );
В чем разница между этими двумя вызовами assign()?Какой их них предпочтительнее и почему?
ps.get()->assign( "Danny" ); |