Odgadnę dziko:
Konstruktor i destruktor C ++ wcale nie są funkcjami: są makrami. Wchodzą one w zakres, w którym obiekt jest tworzony, i zakres, w którym obiekt jest niszczony. Z kolei nie ma konstruktora ani destruktora, obiekt po prostu JEST.
Właściwie myślę, że inne funkcje w klasie nie są również funkcjami, ale funkcjami wbudowanymi, które NIE są wprowadzane, ponieważ przyjmujesz ich adres (kompilator zdaje sobie sprawę, że na nim jesteś, nie wstawia ani nie wstawia kodu do funkcji i optymalizuje tę funkcję), a z kolei funkcja wydaje się „nadal tam być”, nawet jeśli nie zrobiłbyś tego, gdybyś jej nie wziął pod uwagę.
Wirtualna tabela „obiektu” C ++ nie jest jak obiekt JavaScript, w którym można uzyskać jego konstruktor i tworzyć z niego obiekty w czasie wykonywania new XMLHttpRequest.constructor, ale raczej zbiór wskaźników do anonimowych funkcji, które działają jak środek do komunikacji z tym obiektem , z wyłączeniem możliwości utworzenia obiektu. I nawet nie ma sensu „usuwać” obiektu, ponieważ jest to jak próba usunięcia struktury, nie możesz: to tylko etykieta stosu, po prostu napisz do niego, jak chcesz, pod inną etykietą: możesz użyj klasy jako 4 liczb całkowitych:
/* i imagine this string gets compiled into a struct, one of which's members happens to be a const char * which is initialized to exactly your string: no function calls are made during construction. */
std::string a = "hello, world";
int *myInt = (int *)(*((void **)&a));
myInt[0] = 3;
myInt[1] = 9;
myInt[2] = 20;
myInt[3] = 300;
Nie ma przecieku pamięci, nie ma problemów, oprócz tego, że skutecznie zmarnowałeś garść miejsca na stosie, które jest zarezerwowane dla interfejsu obiektów i łańcucha, ale nie zniszczy twojego programu (dopóki nie spróbujesz go użyć jako ciąg ponownie).
W rzeczywistości, jeśli moje wcześniejsze założenia są poprawne: całkowity koszt łańcucha to tylko koszt przechowywania tych 32 bajtów i stałej przestrzeni łańcucha: funkcje są używane tylko w czasie kompilacji, a po zakończeniu mogą być również wstawiane i odrzucane obiekt jest tworzony i używany (tak jakbyś pracował ze strukturą i odwoływał się do niej bezpośrednio, bez żadnych wywołań funkcji, to na pewno są powielone wywołania zamiast skoków funkcji, ale zwykle jest to szybsze i zajmuje mniej miejsca). W istocie, za każdym razem, gdy wywołujesz dowolną funkcję, kompilator po prostu zastępuje to wywołanie instrukcjami, aby dosłownie to zrobić, z wyjątkami ustawionymi przez projektantów języka.
Podsumowanie: obiekty C ++ nie mają pojęcia, czym są; wszystkie narzędzia do łączenia się z nimi są wbudowane statycznie i utracone w czasie wykonywania. To sprawia, że praca z klasami jest tak wydajna jak wypełnianie struktur danymi i bezpośrednia praca z tymi danymi w ogóle bez wywoływania jakichkolwiek funkcji (funkcje te są wbudowane).
Jest to całkowicie odmienne od podejść COM / ObjectiveC, a także javascript, które dynamicznie przechowują informacje o typie, kosztem narzutu, zarządzania pamięcią, wywołań konstrukcji, ponieważ kompilator nie może wyrzucić tych informacji: jest to konieczne do wysyłki dynamicznej. To z kolei daje nam możliwość „rozmawiania” z naszym programem w czasie wykonywania i rozwijania go podczas działania, dzięki posiadaniu elementów odblaskowych.