C++: библиотека программиста



Download 1,95 Mb.
Pdf ko'rish
bet110/144
Sana24.02.2022
Hajmi1,95 Mb.
#223123
TuriРеферат
1   ...   106   107   108   109   110   111   112   113   ...   144
Bog'liq
C -Eldjer-Djeff-for-Real-Programmers-RUS-www.itlibitum.ru

 
197 
Аргументы оператора new 
Оператор 
new
можно перегрузить так, чтобы помимо размера он вызывался и с другими 
дополнительными аргументами. Перегрузка лишает вас стандартной сигнатуры 
void* operator 
new(size_t)
, и, если вам этого не хочется, ее придется включить в программу вручную. 
#define kPoolSize 4096 
struct Pool { 
unsigned char* next; 
// Следующий свободный байт 
unsigned char space[kPoolSize]; 
Pool() : next(&space[0]) {} 
}; 
class Foo { 
public: 
void* operator new(size_t bytes) 
{ return ::operator new(bytes); } 
void* operator new(size_t bytes, Pool* pool) 

void* space = pool->next; 
pool->next 
+= 
bytes; 
return 
space; 

}; 
void f() 

Pool 
localPool; 
Foo* foo1 = new Foo; 
// Использует оператор new по умолчанию 
Foo* foo2 = new(&localPool) Foo; 
// Использует перегрузку 

Здесь клиент, а не класс указывает, где следует разместить объект. Показан лишь фрагмент полной 
стратегии. Например, как оператор 
delete
узнает, откуда была взята память — из глобального пула, 
используемого оператором 
new
по умолчанию, или настандартного пула, который используется 
перегруженным оператором 
new
? Впрочем, основная идея проста: предоставить клиенту класса 
некоторую степень контроля над размещением экземпляров в памяти. Это означает, что способ 
выделения памяти может выбираться для конкретных объектов и не обязан совпадать для всех 
экземпляров класса. 
Оператор new можно перегружать с любыми новыми сигнатурами при условии, что все они 
различаются, а первым аргументом каждой перегруженной версии является 
size_t
— количество 
нужных байт. Перегрузки могут быть как глобальными, так и принадлежать конкретным классам. 
Когда компилятор встречает аргументы между 
new
и именем класса, он подставляет размер в начало 
списка аргументов и ищет подходящую сигнатуру. 
Конструирование с разделением фаз 
Эта идиома предложена Джеймсом Коплином (James Coplien), который назвал ее «виртуальным 
конструктором». Что делает следующий перегруженный оператор 
new

class Foo { 
public: 
void* operator new(size_t, void* p) { return p; } 
}; 
На первый взгляд — ничего; пустая трата времени. Но так ли это? Что произойдет в следующем 
фрагменте? 


 198 
union U { 
Foo 
foo; 
Bar 
bar; 
Banana 
banana; 
}; 
U whatIsThis; 
Компилятор С++ не может определить, какой конструктор следует вызывать для 
whatIsThis
— 
Foo::Foo()

Bar::Bar()
или 
Banana::Banana()
. Разумеется, больше одного конструктора 
вызывать нельзя, поскольку все члены занимают одно и то же место в памяти, но без инструкций от вас 
не может выбрать нужный конструктор. Как и во многих других ситуациях, компилятор поднимет 
руки; он сообщает об ошибке и отказывается принимать объединение, члены которого имеют 
конструкторы. Если вы хотите, чтобы одна область памяти могла инициализироваться несколькими 
различными способами, придется подумать, как обмануть компилятор. Описанный выше «пустой» 
конструктор подойдет лучше всего. 
unsigned char space[4096]; 
Foo* whatIsThis = new(&space[0]) Foo; 
Фактически происходит то, что в С++ происходить не должно — вызов конструктора. При этом память 
на выделяется и не освобождается, поскольку оператор 
new
ничего не делает. Тем не менее, 
компилятор С++ сочтет, что это новый объект, и все равно вызовет конструктор. Если позднее вы 
передумаете и захотите использовать ту же область памяти для другого объекта, то сможете снова 
вызвать хитроумный оператор 
new
и инициализировать ее заново. 
При создании объекта оператором new компилятор всегда использует двухшаговый процесс: 
1. Выделение памяти под объект. 
2. Вызов конструктора объекта. 
Этот код запрятан в выполняемом коде, генерируемом компилятором, и в обычных ситуациях второй 
шаг не выполняется без первого. Идиома виртуального конструктора позволяет надеть повязку на глаза 
компилятору и обойти это ограничение. 
Оперативное изменение типа объекта 
Если позднее 
Foo
вам надоест и вы захотите использовать ту же область для 
Banana
, то при наличии у 
Banana того же перегруженного оператора new вы сможете быстро сменить тип объекта. 
Banana* b = new(&space[0]) Banana; 
Пуф! Был 
Foo
, стал 
Banana
. Это и называется идиомой виртуального конструктора. Такое решение 
полностью соответствует спецификации языка. 
Ограничения 
Применяя эту идиому, необходимо помнить о двух обстоятельствах: 
1. Область, передаваемая оператору 
new
, должна быть достаточна для конструирования класса. 
2. Об изменении должны знать все клиенты, хранящие адрес объекта! 
Будет весьма неприятно, если вы сменили тип объекта с 
Foo
на 
Banana
только для того, чтобы какой-
нибудь клиентский объект тут же вызвал одну из функций 
Foo

Уничтожение с разделением фаз 
Объект, переданный в качестве аргумента оператору 
delete
, обычно уничтожается компилятором в 
два этапа: 
1. Вызов деструктора. 
2. Вызов оператора 
delete
для освобождения памяти. 
Довольно часто мы качаем головой и говорим: «Хорошо бы вызвать деструктор, но не трогать память». 
Допустим, вы разместили объект в пуле, а теперь не хотите, чтобы часть локально созданного пула 



Download 1,95 Mb.

Do'stlaringiz bilan baham:
1   ...   106   107   108   109   110   111   112   113   ...   144




Ma'lumotlar bazasi mualliflik huquqi bilan himoyalangan ©hozir.org 2024
ma'muriyatiga murojaat qiling

kiriting | ro'yxatdan o'tish
    Bosh sahifa
юртда тантана
Боғда битган
Бугун юртда
Эшитганлар жилманглар
Эшитмадим деманглар
битган бодомлар
Yangiariq tumani
qitish marakazi
Raqamli texnologiyalar
ilishida muhokamadan
tasdiqqa tavsiya
tavsiya etilgan
iqtisodiyot kafedrasi
steiermarkischen landesregierung
asarlaringizni yuboring
o'zingizning asarlaringizni
Iltimos faqat
faqat o'zingizning
steierm rkischen
landesregierung fachabteilung
rkischen landesregierung
hamshira loyihasi
loyihasi mavsum
faolyatining oqibatlari
asosiy adabiyotlar
fakulteti ahborot
ahborot havfsizligi
havfsizligi kafedrasi
fanidan bo’yicha
fakulteti iqtisodiyot
boshqaruv fakulteti
chiqarishda boshqaruv
ishlab chiqarishda
iqtisodiyot fakultet
multiservis tarmoqlari
fanidan asosiy
Uzbek fanidan
mavzulari potok
asosidagi multiservis
'aliyyil a'ziym
billahil 'aliyyil
illaa billahil
quvvata illaa
falah' deganida
Kompyuter savodxonligi
bo’yicha mustaqil
'alal falah'
Hayya 'alal
'alas soloh
Hayya 'alas
mavsum boyicha


yuklab olish