ďťż

Ładny brzuch

Witam!

Miałem zrobić takie ćwiczenie pod koniec działu o przeładowanych operatorach:


Napisz definicję klasy, a w niej definicję przeładowanego operatora new, który przy tworzeniu pierwszego obiektu tej klasy od razu zarezerwuje pamięć na 100 takich obiektów. Potem, przy każdym następnym użyciu operatora new, będzie on po prostu przydzielał fragment tego zapasu, który zrobił. Obiektu mogą być tworzone i likwidowane, a operator powinien umieć tą pamięcią gospodarować. W przypadku likwidacji ostatniego obiektu tej klasy, operator delete zwolni tę "100 obiektową" rezerwację.

Prosty program, ale odnośnie jednej rzeczy mam pytanie. Kiedy przekroczymy rezerwację, tzn. wykorzystaliśmy już 100 obiektów to teraz nie pozostaje nic innego niż ustawienie składnika statycznego ktory_raz na 0. I tutaj jest właśnie wg mnie minus tego programu - jeżeli pierwszy wskaźnik miał nazwę wektor_sily, potem w programie wykorzystaliśmy te 100 obiektów i zaczynamy od zera to teraz jak zdefiniujemy wskaźnik predkosc i będziemy chcieli usunąć delet'em - albo 1-szy albo 2-gi - to tylko jeden. Usunięcie jednego spowoduje usunięcie drugiego. Tego minusu nie da się chyba naprawić, co ?

#include <iostream> using namespace std; ////////////////////////////////////////////////// class wektor { int x, y; static int *wsk[100]; static int ktory_raz; public: //------------konstruktor wektor(int a = 0, int b = 0) : x(a), y(b) { } //################################################### //############# PRZEŁADOWANE OPERATORY ############## //--------------------------------------------------- //--------------------------------------------------- static void* operator new(size_t rozmiar) { if(ktory_raz == 0) { for(int i = 0; i < 100; i++) { wsk[i] = new int[rozmiar]; } return wsk[ktory_raz++]; } else { if(ktory_raz == 100) //jeżeli zapełniliśmy całą tablicę wskaźników { //to zaczynamy od początku (ktory_raz = 0) //odbędzie się nadpisanie ! ktory_raz = 0; } return wsk[ktory_raz++]; } } //--------------------------------------------------- //--------------------------------------------------- static void operator delete(void *do_skasowania) { if(ktory_raz == 100) { for(int i = 0; i < 100; i++) //jeżeli ktory_raz jest równy 100 delete wsk[i]; //to zwalniamy całą rezerwację } else { int ktory_numer; for(int i = 0; i <= 100; i++) { ktory_numer = i; if(wsk[i] == do_skasowania) //musimy wyszukać w naszej rezerwacji adres { //obiektu na rzecz, którego chcemy wykonać break; //zwolnienia pamięci } } delete wsk[ktory_numer]; } } //--------------------------------------------------- //--------------------------------------------------- }; ////////////////////////////////////////////////// int* wektor::wsk[100]; //definicje obiektów statycznych klasy 'wektor' int wektor::ktory_raz; int main() { wektor* wektor_sily; //ktory_raz = 0 wektor_sily = new wektor; wektor* wektor_predkosci; //ktory_raz = 1 wektor_predkosci = new wektor; wektor* tabl[98]; //ktory_raz = 99 for(int i = 0; i < 98; i++) { tabl[i] = new wektor; } //ktory_raz wynosi: 100 wektor* predkosc = new wektor; //ktory_raz wynosi: 1 delete wektor_sily; //i teraz się skasuje wsk[0] //delete predkosc; <----- no i teraz byłby błąd - o tym mówiłem właśnie }

Z góry jak zwykle - dziękuję za pomocne rady.



Zwróć uwagę, że zadanie jednak nie specyfikuje co zrobić w granicznej sytuacji. Dlatego zamiast kombinować lepiej zwracać NULL, a jeszcze lepiej rzucić std::bad_alloc(). Chciałbyś kiedyś pisząc jakiś program stworzyć n obiektów gdzie n+1 będzie sam z siebie zmieniał 1? Niespecjalne rozwiązanie :)
Pozostaje jeszcze kwestia segfaulta. Twój operator tak naprawdę zwalnia pamięć dwa razy. Jak wywołasz delete przy liczniku 100 leci w niepamięć cała tablica, a z każdym kolejnym delete usuwasz już zwolnione elementy z tablicy. Lepiej będzie jeżeli usuniesz całą tablicę razem z ostatnim obiektem. Pojedyncze elementy nie są tutaj aż tak bardzo istotne, a zawsze możesz jakoś je oznaczyć i zerować dając użytkownikowi wrażenie nowego obiektu.

  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • zsf.htw.pl
  •