Чтение онлайн

на главную - закладки

Жанры

Шрифт:

5.5.3 Свободная память

Рассмотрим:

main (* table* p = new table(100); table* q = new table(200); delete p; delete p; // возможно, ошибка *)

Конструктор table::table будет вызван дважды, как и деструктор table::~table. То, что С++ не дает никаких грантий, что для объекта, созданного с помощью new, когда-либо будет вызван деструктор, ничего не значит. В предыдущей прорамме q не уничтожается, а p уничтожается дважды! Программист может счесть это ошибкой, а может и не счесть, в зависимости от типа p и q. Обычно то, что объект

не уничтожается, являеся не ошибкой, а просто лишней тратой памяти. Уничтожение p дважды будет, как правило, серьезной ошибкой. Обычно резултатом применения delete дважды к одному указателю приводит к бесконечному циклу в подпрограмме управления свободной пмятью, но определение языка не задает поведение в таком слчае, и оно зависит от реализации.

Пользователь может определить новую реализацию операций new и delete (см. #3.2.6). Можно также определить способ взимодействия конструктора или деструктора с операциями new и delete (см. #5.5.6)

5.5.4 Объекты класса как члены

Рассмотрим

class classdef (* table members; int no_of_members; // ... classdef(int size); ~classdef; *);

Очевидное намерение состоит в том, что classdef должен содержать таблицу длиной size из членов members, а сложность – в том, как сделать так, чтобы конструктор table::table вызывался с параметром size. Это делается так:

classdef::classdef(int size) : members(size) (* no_of_members = size; // ... *)

Параметры для конструктора члена (здесь это table::table ) помещаются в определение (не в описание) конструктора класса, вмещающего его (здесь это classdef::classdef). Поле этого конструктор члена вызывается перед телом конструктра, задающего его список параметров.

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

class classdef (* table members; table friends; int no_of_members; // ... classdef(int size); ~classdef; *);

Список параметров для членов разделяется запятыми (а не двоеточиями), и список инициализаторов для членов может представляться в произвольном порядке:

classdef::classdef(int size)

: friends(size), members(size) (* no_of_members = size; // ... *)

Порядок, в котором вызываются конструкторы, неопределен, поэтому не рекомендуется делать списки параметров с побочными эффектами:

classdef::classdef(int size) : friends(size=size/2), members(size); // дурной стиль (* no_of_members = size; // ... *)

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

classdef::classdef(int size) : members(size) (* no_of_members = size; // ... *)

и размер size таблицы friends будет равен 15.

Когда объект класса, содержащий объект класса, (напрмер, classdef) уничтожается, первым выполняется тело собтвенного деструктора объекта, а затем выполняются деструкторы членов.

Рассмотрим традиционную альтернативу тому, чтобы

иметь объекты класса как члены, – иметь члены указатели и инициалзировать их в конструкторе:

class classdef (* table* members; table* friends; int no_of_members; // ... classdef(int size); ~classdef; *);

classdef::classdef(int size) (* members = new table(size); friends = new table; // размер таблицы по умолчанию no_of_members = size; // ... *)

Так как таблицы создавались с помощью new, они должны уничтожаться с помощью delete:

classdef::~classdef (* // ... delete members; delete friends; *)

Раздельно создаваемые объекты вроде этих могут оказаться полезными, но учтите, что members и friends указывают на одельные объекты, что требует для каждого из них действие по выделению памяти и ее освобождению. Кроме того, указатель плюс объект в свободной памяти занимают больше места, чем объект член.

5.5.5 Вектора объектов класса

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

table tblvec[10];

будет ошибкой, так как для table::table требуется целый параметр. Нет способа задать параметры конструктора в описании вектора. Чтобы можно было описывать вектор таблиц table, можно модифицировать описание table (#5.3.1), напрмер, так:

class table (* // ... void init(int sz); // как старый конструктор public: table(int sz) // как раньше, но без по умолчанию (* init(sz); *) table // по умолчанию (* init(15); *) *)

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

void f (* table* t1 = new table; table* t2 = new table[10]; delete t1; // одна таблица delete t2; // неприятность: 10 таблиц *)

В этом случае длину вектора должен задавать программист:

void g(int sz) (* table* t1 = new table; table* t2 = new table[sz]; delete t1; delete[] t2; *)

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

5.5.6 Небольшие объекты

Когда вы используете много небольших объектов, размещамых в свободной памяти, то вы можете обнаружить, что ваша

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

Поделиться:
Популярные книги

Танцы с огнем

Робертс Нора
Любовные романы:
остросюжетные любовные романы
8.68
рейтинг книги
Танцы с огнем

Казачество в 1812 году

Шишов Алексей Васильевич
История казачества
Научно-образовательная:
история
5.00
рейтинг книги
Казачество в 1812 году

Старый, но крепкий 4

Крынов Макс
4. Культивация без насилия
Фантастика:
уся
фэнтези
5.00
рейтинг книги
Старый, но крепкий 4

Том 11. По Руси. Рассказы 1912-1917

Горький Максим
11. Собрание сочинений в тридцати томах
Проза:
русская классическая проза
5.00
рейтинг книги
Том 11. По Руси. Рассказы 1912-1917

Корабль судьбы. Том 2

Хобб Робин
3. Сага о живых кораблях
Фантастика:
фэнтези
9.15
рейтинг книги
Корабль судьбы. Том 2

Космические скитальцы (Сборник)

Лейнстер Мюррей
Классика мировой фантастики
Фантастика:
боевая фантастика
6.25
рейтинг книги
Космические скитальцы (Сборник)

Точка Бифуркации VI

Смит Дейлор
6. ТБ
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Точка Бифуркации VI

Краткий справочник необходимых знаний

Чернявский Андрей Владимирович
Домашняя библиотека
Научно-образовательная:
прочая научная литература
7.33
рейтинг книги
Краткий справочник необходимых знаний

Далекие королевства

Банч Кристофер
1. Далекие Королевства
Фантастика:
фэнтези
7.75
рейтинг книги
Далекие королевства

Меч Предназначения

Сапковский Анджей
2. Ведьмак
Фантастика:
фэнтези
9.35
рейтинг книги
Меч Предназначения

Двадцать один год

Кинешемцева Мелания
Любовные романы:
прочие любовные романы
5.00
рейтинг книги
Двадцать один год

Последний реанорец. Том X

Павлов Вел
9. Высшая Речь
Фантастика:
фэнтези
попаданцы
аниме
5.25
рейтинг книги
Последний реанорец. Том X

Газлайтер. Том 19

Володин Григорий Григорьевич
19. История Телепата
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Газлайтер. Том 19

Дважды одаренный. Том VII

Тарс Элиан
7. Дважды одаренный
Фантастика:
аниме
фэнтези
попаданцы
5.40
рейтинг книги
Дважды одаренный. Том VII