Konteyner va uni qo‘llanilishi - Tiplarni dinamik tarzda aniqlash. Reja: Tiplarni dinamik tarzda aniqlash

|
Tiplarni dinamik tarzda aniqlash. Reja: Tiplarni dinamik tarzda aniqlash
|
bet | 53/143 | Sana | 20.07.2024 | Hajmi | 0,81 Mb. | | #268096 |
Bog'liq Tiplarni dinamik tarzda-fayllar.orgKonteyner va uni qo‘llanilishi. Xotirada ko‘p hollarda merosxo‘r obʻyektlarini saqlovchi sinflar vujudga keladi. Ularning xotiradan o‘chirilishi bazaviy sinf bilan bog‘liqdir. Masalan, sinf bo‘lsin va tugun ichidagi matndan olingan mo‘rosxo‘rlari Node va Attribute hamda (char*) qatorlardan to‘ldirilgan. Yoki papkani qayta o‘qish va yana o‘zgartirishda, bir marta yuklanadi fayl menejeri fayllar va kataloglar ro‘yxati.
Yuqorida ko‘rsatilgandek, new operatoriga nisbattan delete operatori foydalanish qiyinroq va muammoliroq bo‘ladi. Bazaviy sinf obʻyekti bilan bog‘liq katta blokda merosxo‘r sinf obʻyektlari uchun xotira ajratish kerak. Bazaviy sinf obʻyektini yo‘q qilish paytida, destruktor odatdagidek, merosxo‘r sinf uchun chaqiriladi, lekin xotirani qaytarishingiz shart emas — bu katta blokda ozod qilinadi.
PointerBumpAllocator sinf yaratamiz. Bu sinf katta blokdan turli o‘lchamdagi qismlarni kesib tashlash va eskisi tugagach, yangi katta blokni tanlashga imkon beradi.
PointerBumpAllocator sinfining dastur fragmenti.
template class PointerBumpAllocator
{public: PointerBumpAllocator() : free(0) { }
void* AllocBlock(size_t block) {
// todo: lock(this)
block = align(block, Alignment); if (block > free) {
free = align(block, PageSize); head = GetPage(free);
} void* tmp = head;
|
head = (char*)head + block; free -= block;
return tmp;
}
~PointerBumpAllocator() {
for (vector::iterator i = pages.begin(); i != pages.end(); ++i)
{VirtualFree(*i, 0, MEM_RELEASE);}
}
private: void* GetPage(size_t size) {
void* page = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE);
pages.push_back(page); return page;}
vector pages; void* head;
size_t free;};
typedef PointerBumpAllocator<> DefaultAllocator;
|
Nihoyat, new va delete operatorlari bilan childObject ni tuzamiz va berilgan allocator bilan murojaat qilamiz:
template struct ChildObject
{static void* operator new(size_t s, A& allocator) { return allocator.AllocBlock(s);}
static void* operator new(size_t s, A* allocator) { return allocator->AllocBlock(s);}
static void operator delete(void*, size_t) { }
|
static void operator delete(void*, A*) { } static void operator delete(void*, A&) { }
private:
static void* operator new(size_t s);
};
|
Child sinfiga o‘zgaruvchilarni qo‘shish uchun barcha eʻlonlarni new operatori orqali amalga oshirish kerak bo‘ladi. New operatori quyidagicha bo‘ladi.
new (… parametrlar… ) ChildObject (…konstruktor parametrlari… )
|
Qulaylik uchun A& va A* uchun new operatorlarni qo‘llaymiz.
node = new(allocator) XmlNode(nodename);
|
Agar allokator ajratuvchi sifatida qo‘shilsa, ikkinchisidan foydalanish qulayroq:
node = new(this) XmlNode(nodename);
|
Bundan tushinarli bo‘ladiki, ortiqcha belgilardan qochishda amallarni bo‘lish uchun ko‘rsatkich va havolalar konvertatsiya bo‘ladi.
Obʻyekt yaratishda qaysi New operatoridan foydalanganligiga qaramasdan, delete operatori yordamida o‘chirish amalga oshirilmaydi, kompilyatorning o‘zi standart delete operatoridan foydalanadi. Quyidagicha sintaktik asosida:
Agar ChildObject sinfi obʻyekti yoki uning merosxo‘ri obʻyektidan foydalanayotgan bo‘lsangiz, new istisno vaqtida operatoriga mos delete orperatori chaqiriladi. Shuning uchung bu obʻyektdan foydalanganda birinchi size_t parametrni void*ga o‘zgartirish lozim.
New operatorini private bo‘limiga joylashtirish, uni allokatorsiz ishlashaga ruxsat bermaydi.
Standart bo‘yicha taqsimlovchilar.
Tuzilmali o‘zgaruvchisi uchun dinamik xotira ajratish. Tuzilmali o‘zgaruvchisi uchun xotira ajratish va bo‘shatish. Quyidagi tavsifga ega bo‘lgan data tuzilmasi berilgan bo‘lsin:
struct Date tipidagi o‘zgaruvchi uchun xotiradan joy ajratish va foydalanish uchun quyidagicha dastur fragmentini yozish kerak:
5.10-dastur. xotiradan joy ajratish va foydalanish.
#include "stdafx.h" #include using namespace std;
// tuzilma, kun, oy, yil;
struct Date
{int day; int month; int year;};
int main(){ // new operatori bilan xotiradan joy ajratish
struct Date * pd; // struct Date ga koʻrsatkich
try{ pd = new struct Date; // xotiraga joy ajratish
} catch (bad_alloc ba) {cout << "Xorita ajratilmadi" << endl;
return -1;}
// Agar xotira ajratilgan boʻlsa, unga 16.14.2020 qimat qilib beramiz.
pd->day = 16; pd->month = 04; pd->year = 2020;
cout << pd->day << ":" << pd->month << ":" << pd->year << endl;
// pd oʻzgaruvchisini xotiradan boʻshatish
delete pd;system("pause"); return 0;}
| |
| |