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

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

Жанры

Шрифт:

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 Небольшие объекты

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

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

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

Черный Маг Императора 7 (CИ)

Герда Александр
7. Черный маг императора
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Черный Маг Императора 7 (CИ)

Герой

Бубела Олег Николаевич
4. Совсем не герой
Фантастика:
фэнтези
попаданцы
9.26
рейтинг книги
Герой

Тринадцатый XI

NikL
11. Видящий смерть
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Тринадцатый XI

Кодекс Крови. Книга ХIII

Борзых М.
13. РОС: Кодекс Крови
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Кодекс Крови. Книга ХIII

Товарищ "Чума" 4

lanpirot
4. Товарищ "Чума"
Фантастика:
городское фэнтези
альтернативная история
5.00
рейтинг книги
Товарищ Чума 4

Моров. Том 3

Кощеев Владимир
2. Моров
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Моров. Том 3

Княжья Русь

Мазин Александр Владимирович
6. Варяг
Приключения:
исторические приключения
9.04
рейтинг книги
Княжья Русь

Гримуар темного лорда VI

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

Главный рубильник. Расцвет и гибель информационных империй от радио до интернета

Ву Тим
Деловая литература:
о бизнесе популярно
5.00
рейтинг книги
Главный рубильник. Расцвет и гибель информационных империй от радио до интернета

Третье правило диверсанта

Бычков Михаил Владимирович
Фантастика:
постапокалипсис
5.67
рейтинг книги
Третье правило диверсанта

Я еще князь. Книга XX

Дрейк Сириус
20. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я еще князь. Книга XX

Украсть у президента

Гриньков Владимир Васильевич
Детективы:
триллеры
5.00
рейтинг книги
Украсть у президента

Мистики, розенкрейцеры, тамплиеры в Советской России

Никитин Андрей Леонидович
Научно-образовательная:
история
религиоведение
5.00
рейтинг книги
Мистики, розенкрейцеры, тамплиеры в Советской России

Эпоха Опустошителя. Том VIII

Павлов Вел
8. Вечное Ристалище
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Эпоха Опустошителя. Том VIII