Программирование >>  Инициализация объектов класса, структура 

1 ... 223 224 225 [ 226 ] 227 228 229 ... 395


увы! это не совсем правильно

оператор delete. Однако написать

delete pact;

недостаточно, так как pact при этом не идентифицируется как массив объектов. В результате деструктор класса Account применяется лишь к первому элементу массива. Чтобы применить его к каждому элементу, мы должны включить пустую пару скобок

правильно:

показает, что pact адресует массив

между оператором delete и адресом удаляемого объекта:

delete [] pact;

Пустая пара скобок говорит о том, что pact адресует именно массив. Компилятор определяет, сколько в нем элементов, и применяет деструктор к каждому из них.

14.4.1. Инициализация массива, распределенного из хипа A

По умолчанию инициализация массива объектов, распределенного из хипа, проходит в два этапа: выделение памяти для массива, к каждому элементу которого применяется конструктор по умолчанию, если он определен, и последующее присваивание значения каждому элементу.

Чтобы свести инициализацию к одному шагу, программист должен вмешаться и поддержать следующую семантику: задать начальные значения для всех или некоторых элементов массива и гарантировать применение конструктора по умолчанию для тех элементов, начальные значения которых не заданы. Ниже приведено одно из возможных программных решений, где используется оператор размещения new:

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

Объявление

Account *pact = new Account [ 10 ];

создает в памяти, выделенной из хипа, массив из десяти объектов класса Account, причем каждый инициализируется конструктором по умолчанию.

Чтобы уничтожить массив, адресованный указателем pact, необходимо применить



#include <utility> #include <vector

4таа1т,а таатт-т.

#include <new> #include <cstddef>

4таа1т,а Лааапаао

#include Accounts.h

typedef pair<char*, double> value pair; /* init heap array()

объявлена как статическая функция-член обеспечивает в1деление памяти из хипа и инициазацию

* массива объектов

* init values: пары начальных значений

* elem count: число элементов в массиве

значений элементов массива

если 0, то размером массива считается размер вектора init values

Account* Account::

init heap array(

vector<value pair> sinit values, vector<value pair>::size type elem count = 0 )

vector<value pair>::size type

vec size = init value.size();

if ( vec size == 0 && elem count == 0 ) return 0;

/ размер массива равен либо elem count, / либо, если elem count == 0, размеру вектора

размер массива равен либо

size t elems = elem count

? elem count : vec size();

получить блок памяти для размещения массива char *p = new char[sizeof(Account)*elems];

по отдельности инициализировать каждый элемент массива

int offset = sizeof( Account );

for ( int ix = 0; ix < elems; ++ix )

смещение ix-ого элемента если пара начальных значений задана,

передать ее конструктору;

в противном случае вызвать конструктор по умолчанию

if ( ix < vec size )

new( p+offset*ix ) Account( init values[ix].first,

init values[ix].second ); else new( p+offset*ix ) Account;

отлично: элементы распределены и инициализированы; вернуть указатель на первый элемент return (Account*)p;

Необходимо заранее выделить блок памяти, достаточный для хранения запрошенного массива, как массив байт, чтобы избежать применения к каждому элементу конструктора по умолчанию. Это делается в такой инструкции:



for ( int ix = 0; ix < elems; ++ix ) {

if ( ix < vec size )

new( p+offset*ix ) Account( init values[ix].first,

init values[ix].second ); else new( p+offset*ix ) Account;

задана пара начальных значений, либо конструктор по умолчанию:

В разделе 14.3 говорилось, что оператор размещения new позволяет применить конструктор класса к уже выделенной области памяти. В данном случае м1 используем new для поочередного применения конструктора класса Account к каждому из выделенных элементов массива. Поскольку при создании инициализированного массива мы подменили стандартный механизм выделения памяти, то должны сами позаботиться о ее освобождении. Оператор delete работать не будет:

delete [] ps;

Почему? Потому что ps (мы предполагаем, что эта переменная была инициализирована вызовом init heap array() ) указывает на блок памяти, полученный не с помощью стандартного оператора new, поэтому число элементов в массиве компилятору

void

Account::

dealloc heap array( Account *ps, size t elems ) {

for ( int ix = 0; ix < elems; ++ix ) ps[ix].Account::~Account();

delete [] reinterpret cast<char*>(ps);

неизвестно. Так что всю работу придется сделать самим:

Если в функции инициализации мы пользовались арифметическими операциями над указателями для доступа к элементам:

new( p+offset*ix ) Account;

то здесь мы обращаемся к ним, задавая индекс в массиве ps:

ps[ix].Account::~Account();

Хотя и ps, и p адресуют одну и ту же область памяти, ps объявлен как указатель на объект класса Account, а p - как указатель на char. Индексирование p дало бы ix- й байт, а не ix-й объект класса Account. Поскольку с p ассоциирован не тот тин, что нужно,

char *p = new char[sizeof(Account)*elems];

Далее программа в цикле обходит этот блок, присваивая на каждой итерации переменной p адрес следующего элемента и вызывая либо конструктор с двумя параметрами, если



1 ... 223 224 225 [ 226 ] 227 228 229 ... 395

© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика