Выбрать главу

Account pooh_pals[3] = {

Account( "Woozle", 10.0 ),

Account( "Heffalump", 10.0 )

};

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

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

pooh_pals[0];

обращается к Piglet, а

pooh_pals[1];

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

pooh_pals[1]._name != pooh_pals[2]._name;

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

Объявление

Account *pact = new Account[ 10 ];

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

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

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

delete pact;

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

// правильно:

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

delete [] pact;

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

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

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

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

#include utility

#include vector

#include new

#include cstddef

#include "Accounts.h"

typedef pairchar*, double

value_pair;

/* init_heap_array()

* объявлена как статическая функция-член

* обеспечивает выделение памяти из хипа и инициализацию

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

* init_values: пары начальных значений элементов массива

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

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

* init_values

*/

Account*

Account::

init_heap_array(

vectorvalue_pair &init_values,

vectorvalue_pair ::size_type elem_count = 0 )

{

vectorvalue_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;

}

// отлично: элементы распределены и инициализированы;