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 и $$6.7). Кроме
того, можно установить взаимодействие конструктора или деструктора с операциями new и delete (см.
$$5.5.6 и $$6.7.2). Размещение массивов в свободной памяти обсуждается в $$5.5.5.
5.5.4 Объекты класса как члены
Рассмотрим пример:
class classdef {
table
members;
int
no_of_members;
//
...
classdef(int
size);
~classdef();
};
Цель этого определения, очевидно, в том, чтобы classdef содержал член, являющийся таблицей
размером size, но есть сложность: надо обеспечить вызов конструктора 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();
};
Списки параметров для членов отделяются друг от друга запятыми (а не двоеточиями), а список
Бьерн Страуструп.
Язык программирования С++
145
инициализаторов для членов можно задавать в произвольном порядке:
classdef::classdef(int size)
: friends(size), members(size), no_of_members(size)
{
//
...
}
Конструкторы вызываются в том порядке, в котором они заданы в описании класса.
Подобные описания конструкторов существенны для типов, инициализация и присваивание которых
отличны друг от друга, иными словами, для объектов, являющихся членами класса с конструктором,
для постоянных членов или для членов типа ссылки. Однако, как показывает член no_of_members из
приведенного примера, такие описания конструкторов можно использовать для членов любого типа.
Если конструктору члена не требуется параметров, то и не нужно задавать никаких списков параметров.
Так, поскольку конструктор table::table() был определен со стандартным значением параметра, равным
15, достаточно такого определения:
classdef::classdef(int size)
: members(size), no_of_members(size)
{
//
...
}
Тогда размер таблицы friends будет равен 15.
Если уничтожается объект класса, который сам содержит объекты класса (например, classdef), то
вначале выполняется тело деструктора объемлющего класса, а затем деструкторы членов в порядке,
обратном их описанию.
Рассмотрим вместо вхождения объектов класса в качестве членов традиционное альтернативное ему
решение: иметь в классе указатели на члены и инициализировать члены в конструкторе:
class classdef {
table*
members;
table*
friends;
int
no_of_members;
//
...
};
classdef::classdef(int size)
{
members = new table(size);
friends = new table; // используется стандартный
//
размер table
no_of_members = size;
//
...
}
Поскольку таблицы создавались с помощью операции new, они должны уничтожаться операцией delete:
classdef::~classdef()
{
//
...
delete
members;
delete
friends;
}
Такие отдельно создаваемые объекты могут оказаться полезными, но учтите, что members и friends
указывают на независимые от них объекты, каждый из которых надо явно размещать и удалять. Кроме
того, указатель и объект в свободной памяти суммарно занимают больше места, чем объект-член.
Бьерн Страуструп.
Язык программирования С++
146
Достарыңызбен бөлісу: |