CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - Usunięcie dynamicznie utworzonych komponentów

Usunięcie dynamicznie utworzonych komponentów

dział ogólny

Usunięcie dynamicznie utworzonych komponentów

Nowy postprzez swiezak » wtorek, 15 marca 2011, 01:56

Witam,
Utworzyłem sobie kilka komponentów typu TLabel,

KOD cpp:     UKRYJ  
        Napisy = new TLabel*[LiczbaNapisow];
                for (int i=1; i<LiczbaNapisow; i++)
        {
                Napisy[i]=new TLabel(this);
                Napisy[i]->Parent=ScrollBox1;
                Napisy[i]->Width=50;
                Napisy[i]->Top=50+30*i;
                Napisy[i]->Left=500;
                Napisy[i]->Caption=FloatToStr(i);
        }



ale nie wiem za bardzo jak mam je usunąć by zniknęły z formatki zwalniając przy tym pamięć?
Avatar użytkownika
swiezak
Bladawiec
Bladawiec
 
Posty: 25
Dołączył(a): sobota, 25 grudnia 2010, 02:25
Podziękował : 13
Otrzymał podziękowań: 0
System operacyjny: Windows 7 x64
Kompilator: Embarcadero C++ Builder 2010
Gadu Gadu: 0
    Windows 7Chrome

Re: Usunięcie dynamicznie utworzonych komponentów

Nowy postprzez Cyfrowy Baron » wtorek, 15 marca 2011, 10:30

Źle tworzysz te dynamiczne komponenty i masz tutaj gigantyczny wyciek pamięci. Chcesz tworzyć dynamicznie obiekty w oparciu o tablicę, to powinieneś okreslić rozmiar tej tablicy z góry, czyli ustalić maksymalną liczbę takich obiektów.

Plik nagłówkowy np. Unit1.h
KOD cpp:     UKRYJ  
private:
        TLabel *Napisy[100]; /* maksymalnie 100 obiektów typu TLabel */


Plik źródłowy np. Unit1.cpp
KOD cpp:     UKRYJ  
 for (int i = 1; i < LiczbaNapisow; i++)
 {
  if(i > 100) break;

  Napisy[i] = new TLabel(this);
  Napisy[i]->Name = "Napisy" + (String)i; /* nadaj nazwę */

  Napisy[i]->Parent = ScrollBox1;
  Napisy[i]->Width = 50;
  Napisy[i]->Top = 50+30*i;
  Napisy[i]->Left = 500;
  Napisy[i]->Caption = FloatToStr(i);
 }


Gdy masz komponenty i ich nazwy niszczysz je poprzez nazwę:

KOD cpp:     UKRYJ  
delete Napisy1;


Jeżeli chcesz tworzyć komponenty w nieokreślonej ilości, to posłuż się vector'ami i zapoznaj się z tym wątkiem: http://programowanie.cal.pl/forum/viewtopic.php?f=2&t=1136&p=7809&hilit#p7804
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4719
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Usunięcie dynamicznie utworzonych komponentów

Nowy postprzez Corvis » wtorek, 15 marca 2011, 10:42

Baronie, nie lepiej to ładować to TObjectList ?? i potem wywalać całą liste ?? Nie trzeba się martwić o zwalnianie każdego elementu gdyż usunięcie całej listy automatycznie zwolni każdy jej element.
"Sukcesy trwają, dopóki ich ktoś nie spieprzy. Porażki są wieczne"

Dr Gregory House
Avatar użytkownika
Corvis
Programista I
Programista I
 
Posty: 880
Dołączył(a): sobota, 26 lipca 2008, 00:31
Podziękował : 80
Otrzymał podziękowań: 30
System operacyjny: WINDOWS 7 64-bity
Kompilator: Praca - C++ Builder XE2 ENTERPRISE - Update 4, Dom - C++ Builder XE4 - Uddate 1
Gadu Gadu: 0
    Windows VistaChrome

Re: Usunięcie dynamicznie utworzonych komponentów

Nowy postprzez polymorphism » wtorek, 15 marca 2011, 11:12

Źle tworzysz te dynamiczne komponenty i masz tutaj gigantyczny wyciek pamięci. Chcesz tworzyć dynamicznie obiekty w oparciu o tablicę, to powinieneś okreslić rozmiar tej tablicy z góry, czyli ustalić maksymalną liczbę takich obiektów.

Nie wiem, gdzie Ty tu widzisz wyciek (pomijam sprawę czyszczenia i usuwania tej tablicy, wszak jest to przedmiot tego wątku). Jak na moje oko wszystko jest ok (no, może nie wszystko. Nie rozumiem, dlaczego indeksuje od jednego).

@swiezak: jeśli chodzi o zwalnianie, robisz to w odwrotnej kolejności do tworzenia:
KOD cpp:     UKRYJ  
for (int i = 1; i < LiczbaNapisow; i++)
{
        delete Napisy[ i ];
}

delete[] Napisy;


Potwierdzę to, co było napisane wcześniej. Zamiast bawić się gołymi tablicami dynamicznymi, użyj vectora lub klasy TObjectList. W przypadku klas pochodnych od TObject, a do tych niewątpliwie zaliczają się labele, druga opcja wydaje się sensowniejsza.
C++ Reference - opis wszystkich klas STL-a i funkcji C.

Za ten post autor polymorphism otrzymał podziękowanie od:
swiezak
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2157
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 19
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Usunięcie dynamicznie utworzonych komponentów

Nowy postprzez Cyfrowy Baron » wtorek, 15 marca 2011, 11:40

polymorphism napisał(a):Nie wiem, gdzie Ty tu widzisz wyciek


U mnie ten kod:

KOD cpp:     UKRYJ  
 Napisy = new TLabel*[LiczbaNapisow];


wogóle się nie kompiluje, otrzymuję komunikat błędu:


[BCC32 Error] Unit1.cpp(44): E2034 Cannot convert 'TLabel * *' to 'TLabel *'



Nie wiem więc jak może wyglądać deklaracja obiektu Napisy, by ten kod się wogóle skompilował. Dlatego przyjąłem takie rozwiązanie dla testu:

Plik nagłówkowy np. Unit1.h
KOD cpp:     UKRYJ  
private:        // User declarations
       TLabel *Napisy[];


Plik źródłowy np. Unit1.cpp
KOD cpp:     UKRYJ  
 int LiczbaNapisow = 10;

 for (int i=1; i<LiczbaNapisow; i++)
 {
 Napisy[i]=new TLabel(this);
 Napisy[i]->Parent = Form1;//ScrollBox1;
 Napisy[i]->Width=50;
 Napisy[i]->Top = 50 + 30*i;
 Napisy[i]->Left=80;
 Napisy[i]->Caption=FloatToStr(i);
 }


To jednak wywołuje błąd. Program nie daje się zamknąć. Zakładam więc, że są jakieś problemy z adresami. Po określeniu rozmiaru tablicy problemy znikają.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4719
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Usunięcie dynamicznie utworzonych komponentów

Nowy postprzez polymorphism » wtorek, 15 marca 2011, 11:44

Nie wiem więc jak może wyglądać deklaracja obiektu Napisy, by ten kod się wogóle skompilował

W treści błędu masz nawet podpowiedź:
KOD cpp:     UKRYJ  
TLabel** Napisy;
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2157
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 19
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Usunięcie dynamicznie utworzonych komponentów

Nowy postprzez Cyfrowy Baron » wtorek, 15 marca 2011, 12:07

polymorphism napisał(a):W treści błędu masz nawet podpowiedź:


Kombinowałem, ale nie wiedzieć dlaczego nieco inaczej:

  kod niepoprawny
  
KOD cpp:     UKRYJ  
TLabel** Napisy[];
  




Co się tyczy TObjectList to skoro powiedziało się A to należałoby powiedzieć i B.

Plik nagłówkowy np. Unit1.h
KOD cpp:     UKRYJ  
private:        // User declarations
       TObjectList *LabelList;


Plik źródłowy np. Unit1.cpp
KOD cpp:     UKRYJ  
/* konstruktor klasy formularza */
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
 LabelList = new TObjectList();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
 /* dodawanie nowych obiektów do listy, co jest tutaj równoznaczne z ich tworzeniem */
 static int nr = 0;

 int posY = 50;

 TLabel *Label = new TLabel(this);
 Label->Parent = this;
 Label->Left = 80;
 Label->Top = posY + (30 * nr);
 Label->Caption = "Label" + (String)nr;

 LabelList->Add(Label);

 nr++;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
 /* odwoływanie się do konkretnego elementu listy z wykorzystaniem polimorfizmu */

 dynamic_cast<TLabel*>( LabelList->Items[2] )->Caption = "Zmiana etykiety"; /* Items[2] - trzeci element listy licząc o 0 */
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
 /* usuwanie konkretnego obiektu */
 LabelList->Remove( dynamic_cast<TLabel*>( LabelList->Items[2] ) ); /* trzeci obiekt */

 /* usuwanie obiektu poprzez usunięcie elementu listy */
 LabelList->Delete(5);  /* szósty element */
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button4Click(TObject *Sender)
{
 /* usuniecie wszystkich obiektów poprzez wyczyszczenie zawartości listy */
 LabelList->Clear();
}


Przy kasowaniu wybranego elementu z listy lub konkretnego obiektu (to samo) należy pamiętać, że elementy znajdujące się poniżej tego elementu przesuną się do góry listy, zajmując miejsce usuniętego elementu.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4719
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Usunięcie dynamicznie utworzonych komponentów

Nowy postprzez Corvis » wtorek, 15 marca 2011, 12:23

Bardziej mi chodziło, o to czy ten sposób nie jest lepszy niż wektor lub ten co podałeś, niż o pisanie kodu :-). Ok następnym razem podam też kod
"Sukcesy trwają, dopóki ich ktoś nie spieprzy. Porażki są wieczne"

Dr Gregory House
Avatar użytkownika
Corvis
Programista I
Programista I
 
Posty: 880
Dołączył(a): sobota, 26 lipca 2008, 00:31
Podziękował : 80
Otrzymał podziękowań: 30
System operacyjny: WINDOWS 7 64-bity
Kompilator: Praca - C++ Builder XE2 ENTERPRISE - Update 4, Dom - C++ Builder XE4 - Uddate 1
Gadu Gadu: 0
    Windows VistaChrome

Re: Usunięcie dynamicznie utworzonych komponentów

Nowy postprzez Cyfrowy Baron » wtorek, 15 marca 2011, 12:38

Ja tylko zwróciłem uwagę, że jeżeli proponuje się jakieś rozwiązanie początkującemu użytkownikowi, to powinno się podać sposób użycia.

Corvis napisał(a):czy ten sposób nie jest lepszy niż wektor


Moim zdaniem jest po prostu inny. Być może obiekt TObjectList bazuje na czymś podobnym do vector'a. Posługiwanie się listą jest na pewno bardziej zrozumiałe dla kogoś, kto nie ma doświadczenia z vector'ami. Zauważ, że TObjectList oferuje wskaźnik na TObject, a jeżeli stworzysz vektor dla konkretnego typu to możesz odwoływać się bezpośrednio:
vector:
KOD cpp:     UKRYJ  
 LabelList.at(2)->Caption = "jakiś tekst";
 // lub:
 LabelList[2]->Caption = "jakiś tekst";


TObjectList:
KOD cpp:     UKRYJ  
 dynamic_cast<TLabel* >( LabelList->Items[2] )->Caption = "Zmiana etykiety";


W przypadku TObjectList nie można więc odwołać się bezpośrednio do elementu listy, gdyż każdy z tych elementów jest typu TObject, a nie typu przechowywanego obiektu.
Osobiście uważam, że TObjetList jest lepiej użyć tam, gdzie przechowuje się różnego rodzaju obiekty, gdyż w przypadku np. vector'a trzeba by utworzyć kilka list różnych typów.
Poza tym, jeżeli w TObjectList przechowujesz obiekty różnego typu, to przed odwołaniem się do wybranego obiektu w niektórych przypadkach musisz wiedzieć z jakim typem masz do czynienia.
Rodzi się jeszcze pytanie, czy typ TObjectList jest dostępny we wczesnych wersjach środowiska C++Builder.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4719
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox


  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 12 gości

cron