w delphi nic nie dzieje się "automagicznie".
Jak masz w klasie zmienne inne niż typu prostego (integer, char, string, double, ...) lub tablice (dynamiczne i statyczne) to sam musisz je utworzyć oraz w 99,99% przypadków zwolnić. Ten 0,01% to np. wątki, które mają ustawione FreeOnTerminate
na True
czy też elementy listy, która ma ustawione OwnsObjects
na True
. Osobną kwestią są komponenty, które może zwalniać ich właściciel (przekazywany w konstruktorze) w momencie własnej destrukcji. Jest taka zasad mówiąca "co sam stworzyłeś, sam zwolnij". Trzymanie się jej pozwoli Ci zaoszczędzić sobie wiele pracy przy szukaniu przyczyny, że "program cały czas puchnie w pamięci", pozwoli wyeliminować (albo bardziej poprawnie nie powstać) większość wycieków pamięci, jakie zdarzają się początkującym.
Jedynymi elementami, które "zwalniają się same" są interfejsy, które mają licznik odwołań i w momencie, kiedy spadnie on do 0 pamięć po nich jest zwalniana a obiekt niszczony.
A to nie do końca prawda, dzieje się samo w przypadku najnowszej wersji czyli Delphi XE4:
http://blog.marcocantu.com/blog/automatic_reference_counting_for_delphi.html
Są Jeszce kombinacje z tzw. Smart Pointers, ale to inna bajka, za to efekt ten sam. "Magia" w przypadku automatycznego zwalaniania referencji.
http://blog.barrkel.com/2008/09/smart-pointers-in-delphi.html
Co do drugiego pytania to konstruktor nic sam z siebie nie tworzy. Jeśli klasa ma pole, które jest obiektem to właśnie konstruktor jest dobrym miejscem na utworzenie instancji danej klasy a destruktor na jego zniszczenie
Osobiście zamiast przeładować constructori destructor, zalecam napisać metodę AfterConstrucion i BeforeDestruction (są zadeklarowane jako wirtualne publiczne na poziomie TObject).
Co do właściwości, które muszę być zainicjowane to stosuję tzw. lazy create:
type
TMyClass = class
strict private
FSourceConn: TADCustomConnection;
function GetDestConn: TADCustomConnection;
public
property SourceConn: TADCustomConnection read GetSourceConn;
end;
implementation
function TmYcLASS.GetDestConn: TADCustomConnection;
begin
if not Assigned(FSourceConn) then
FSourceConn := TADCustomConnection.Create(nil);
Result := FSourceConn;
end;
Różnica pomiędzy utworzeniem obiektu FConnection w konstruktorze a powyższą metodą jest taka, że to wyżej utworzy ten obiekt dopiero wtedy kiedy będzie potrzebny i nie wcześniej.