Zastanawiałem się, jaki może być rozmiar obiektu z pustej klasy . Z pewnością nie może to być 0 bajtów, ponieważ powinno być możliwe odwoływanie się do niego i wskazywanie go jak każdy inny obiekt. Ale jak duży jest taki obiekt?
Użyłem tego małego programu:
#include <iostream>
using namespace std;
class Empty {};
int main()
{
Empty e;
cerr << sizeof(e) << endl;
return 0;
}
Wynik, który otrzymałem na kompilatorach Visual C ++ i Cygwin-g ++, wynosił 1 bajt ! Było to dla mnie trochę zaskakujące, ponieważ spodziewałem się, że będzie miał rozmiar słowa maszynowego (32 bity lub 4 bajty).
Czy ktoś może wyjaśnić, dlaczego rozmiar 1 bajtu? Dlaczego nie 4 bajty? Czy to zależy także od kompilatora czy maszyny? Czy ktoś może podać bardziej przekonujący powód, dla którego pusty obiekt klasy nie będzie miał rozmiaru 0 bajtów?
Odpowiedzi:
Cytując często zadawane pytania dotyczące stylu i techniki Bjarne Stroustrupa , powodem, dla którego rozmiar jest różny od zera, jest „Aby upewnić się, że adresy dwóch różnych obiektów będą różne”. Rozmiar może wynosić 1, ponieważ wyrównanie nie ma tutaj znaczenia, ponieważ nie ma na co właściwie patrzeć.
źródło
new
; kiedy miejsce jest przydzielane, inna alokacja musi mieć inny adres. I tak dalej. W pustej klasie niekoniecznie występuje żaden wskaźnik; mogą istnieć wskaźniki do zmiennych (lub referencje lub alokacje lokalne / stosu), ale nie mają one rozmiaru zerowego i niekoniecznie są rozmiarem wskaźnika.Standard stwierdza, że wszystkie najbardziej pochodne obiekty mają sizeof ()> = 1:
źródło
To naprawdę szczegół implementacji. Kiedyś myślałem, że może to być zero bajtów lub tysiąc bajtów, że nie ma to wpływu na specyfikację języka. Ale po spojrzeniu na standard (sekcja 5.3.3),
sizeof
jest definiowany jako zawsze zwracający jeden lub więcej, bez względu na wszystko.Jest to wymagane między innymi do obsługi tablic obiektów i wskaźników do nich. Gdyby twoje elementy mogły mieć zerową wielkość,
&(array[0])
byłyby identyczne z&(array[42])
, co spowoduje różnego rodzaju spustoszenie w twoich pętlach przetwarzania.Przyczyną, dla której może to nie być słowo maszynowe, jest to, że nie ma w nim żadnych elementów, które w rzeczywistości wymagają wyrównania na granicy słowa (na przykład liczby całkowitej). Na przykład, jeśli umieścisz
char x; int y;
wewnątrz klasy, moje GCC będzie ją ustawiało na ośmiu bajtach (ponieważ druga int musi być wyrównana w tej implementacji).źródło
Jest wyjątek: tablice o długości 0
źródło
c
,&c[M] == &c[N]
dla każdegoM
iN
(clang ++ 4.1).Mimo że nie jest wymagane przypisywanie jakiejkolwiek pamięci dla pustej klasy, ale aby utworzyć obiekty z pustych klas, kompilator przypisuje minimalną pamięć, którą można przypisać, czyli 1 bajt. W ten sposób kompilator może jednoznacznie rozróżnić dwa obiekty tej samej pustej klasy i będzie mógł przypisać adres obiektu do wskaźnika pustej klasy.
źródło
Myślę, że pomocne może być dodanie linku do odpowiedzi wyjaśniającej to dobre. Jest o
boost::compressed_pair
przez Logan Capaldo .źródło
To może pomóc :-) http://bytes.com/topic/c/insights/660463-sizeof-empty-class-structure-1-a
źródło
Przydział 1 bajtu dla pustej klasy zależy od kompilatora. Kompilatory muszą upewnić się, że obiekty znajdują się w różnych lokalizacjach pamięci i muszą przydzielić niezerowy rozmiar pamięci do obiektu. Posłuchaj uwag na ten temat tutaj: http://listenvoice.com/listenVoiceNote.aspx?id=27
Mimo że kompilatory przydzielają niezerowy rozmiar do pustej klasy, wykonują również optymalizacje, gdy nowe klasy pochodzą z pustych klas. Posłuchaj o optymalizacji pustej bazy w pytaniach o programowanie w C ++ zadawanych przez ListenVoice.
źródło
powodem istnienia klasy bez elementów danych, ale o rozmiarze 1 bajtu jest to, że ten * silny tekst * musi być przechowywany w pamięci, aby odwołanie lub wskaźnik mogły wskazywać na obiekt tej klasy
źródło
pusta klasa - ta klasa nie zawiera żadnej treści.
każda klasa, która nie jest pusta, będzie reprezentowana przez swoją zawartość w pamięci.
teraz jak pusta klasa będzie reprezentowana w pamięci? ponieważ nie ma treści, nie ma sposobu, aby pokazać swoje istnienie w pamięci, ale klasa jest obecna, obowiązkowe jest wykazanie jej obecności w pamięci. Aby pokazać pustą klasę w pamięci, wymagany jest 1 bajt.
źródło
Myślę, że tak jest, ponieważ 1 bajt jest najmniejszą jednostką pamięci, która może być używana jako symbol zastępczy i nie może dać zerowego rozmiaru, ponieważ nie będzie możliwe utworzenie tablicy obiektów.
i to, co powiedziałeś: „To było dla mnie trochę zaskakujące, ponieważ spodziewałem się, że będzie to rozmiar słowa maszynowego (32 bity lub 4 bajty)”. będzie prawdziwe dla zmiennej referencyjnej (słowa macine) typu empty (), a nie rozmiaru samej klasy (która jest abstrakcyjnym typem danych),
źródło
Myślę, że to pytanie jest interesujące tylko teoretycznie, ale nie ma znaczenia w praktyce.
Jak już zauważyli inni, wyprowadzanie z pustej klasy nie powoduje żadnej szkody, ponieważ nie zużywa dodatkowej pamięci dla części klasy bazowej.
Co więcej, jeśli klasa jest pusta (co oznacza, że - teoretycznie - nie potrzebuje żadnej pamięci na instancję, tj. Nie ma żadnych niestatycznych składowych danych ani wirtualnych funkcji składowych), to wszystkie jej funkcje składowe mogą równie dobrze (i powinien) być zdefiniowany jako statyczny. Nie ma więc potrzeby tworzenia instancji tej klasy.
Konkluzja: jeśli napiszesz pustą klasę X, po prostu ustaw wszystkie funkcje składowe jako statyczne. Nie będziesz wtedy musiał tworzyć obiektów X, a klasy pochodne nie będą miały żadnego wpływu.
źródło
Wyjście: OK, dobrze jest mieć różne adresy
Zwrócenie rozmiaru 1 gwarantuje, że dwa obiekty nie będą miały tego samego adresu.
źródło
Jest niezerowe, aby zapewnić, że dwa różne obiekty będą miały różne adresy. Różne obiekty powinny mieć różne adresy, więc rozmiar pustej klasy zawsze wynosi 1 bajt.
źródło
Myślę, że jeśli rozmiar pustej klasy wynosi zero, to znaczy, że nie istnieje. Aby to (klasa) istniało, wymaga co najmniej 1 bajtu, ponieważ ten bajt jest adresem pamięci / odniesienia.
źródło
Dzieje się tak z powodu tego wskaźnika, chociaż wskaźnik ma (liczbę całkowitą) 4 bajty, ale odnosi się do jednej lokalizacji pamięci (jednej jednostki), która ma 1 bajt.
źródło