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

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

Жанры

Шрифт:

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

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

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

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

Телохранитель Генсека. Том 1

Алмазный Петр
1. Медведев
Фантастика:
попаданцы
альтернативная история
7.00
рейтинг книги
Телохранитель Генсека. Том 1

Геном хищника. Книга четвертая

Гарцевич Евгений Александрович
4. Я - Легенда!
Фантастика:
боевая фантастика
рпг
попаданцы
5.00
рейтинг книги
Геном хищника. Книга четвертая

Первый среди равных. Книга VII

Бор Жорж
7. Первый среди Равных
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Первый среди равных. Книга VII

Девочка из прошлого

Тоцка Тала
3. Айдаровы
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Девочка из прошлого

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

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

Отморозок 3

Поповский Андрей Владимирович
3. Отморозок
Фантастика:
попаданцы
5.00
рейтинг книги
Отморозок 3

Барон ломает правила

Ренгач Евгений
11. Закон сильного
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Барон ломает правила

Метатель

Тарасов Ник
1. Метатель
Фантастика:
боевая фантастика
попаданцы
рпг
фэнтези
фантастика: прочее
постапокалипсис
5.00
рейтинг книги
Метатель

Двойник короля 11

Скабер Артемий
11. Двойник Короля
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Двойник короля 11

Двойник короля 20

Скабер Артемий
20. Двойник Короля
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Двойник короля 20

Хозяин Теней 2

Петров Максим Николаевич
2. Безбожник
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Хозяин Теней 2

Двойник короля 19

Скабер Артемий
19. Двойник Короля
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Двойник короля 19

Меченный смертью. Том 5

Юрич Валерий
5. Меченный смертью
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Меченный смертью. Том 5

Кодекс Охотника. Книга XIX

Винокуров Юрий
19. Кодекс Охотника
Фантастика:
фэнтези
5.00
рейтинг книги
Кодекс Охотника. Книга XIX