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

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

Жанры

Шрифт:

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. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 1

Эволюционер из трущоб. Том 5

Панарин Антон
5. Эволюционер из трущоб
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Эволюционер из трущоб. Том 5

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

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

Ефрейтор. Назад в СССР. Книга 2

Гаусс Максим
2. Второй шанс
Фантастика:
попаданцы
альтернативная история
7.00
рейтинг книги
Ефрейтор. Назад в СССР. Книга 2

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

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

Правильный лекарь. Том 8

Измайлов Сергей
8. Неправильный лекарь
Фантастика:
городское фэнтези
аниме
попаданцы
5.00
рейтинг книги
Правильный лекарь. Том 8

Темная сторона. Том 2

Лисина Александра
10. Гибрид
Фантастика:
технофэнтези
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Темная сторона. Том 2

На границе империй. Том 9. Часть 3

INDIGO
16. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 3

Земная жена на экспорт

Шах Ольга
Любовные романы:
любовно-фантастические романы
5.57
рейтинг книги
Земная жена на экспорт

Антимаг его величества

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

Низший - Инфериор. Компиляция. Книги 1-19

Михайлов Дем Алексеевич
Фантастика 2023. Компиляция
Фантастика:
боевая фантастика
5.00
рейтинг книги
Низший - Инфериор. Компиляция. Книги 1-19

Тайные поручения

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

Черный Маг Императора 13

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

Казачий князь

Трофимов Ерофей
5. Шатун
Фантастика:
боевая фантастика
попаданцы
альтернативная история
5.00
рейтинг книги
Казачий князь