С++ для начинающих

Оператор размещения 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());

(h) auto_ptr<int> p7(p2);

Упражнение 8.9

Объясните разницу между следующими инструкциями:

int *pi0 = p2.get();

int *pi1 = p2.release() ;

Для каких случаев более приемлем тот или иной вызов?

Упражнение 8.10

Пусть мы имеем:

auto_ptr< string > ps( new string( "Daniel" ) );

В чем разница между этими двумя вызовами assign()?Какой их них предпочтительнее и почему?

ps.get()->assign( "Danny" );

ps->assign( "Danny" );


Содержание раздела