Бьерн Страуструп. Язык программирования С++ Второе дополненное издание



Pdf көрінісі
бет112/256
Дата11.07.2022
өлшемі2,87 Mb.
#37591
1   ...   108   109   110   111   112   113   114   115   ...   256
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 


Достарыңызбен бөлісу:
1   ...   108   109   110   111   112   113   114   115   ...   256




©emirsaba.org 2024
әкімшілігінің қараңыз

    Басты бет