2016-10-31 16 views
17

Biorąc pod uwagę ten kod:Dlaczego wielokrotne dziedziczenie zwiększa rozmiar obiektu, mimo że bazy są puste?

#include <iostream> 

struct A { 

}; 

struct B { 

}; 

struct C { 

}; 

struct E : A { 
    int field; 
}; 

struct F : A, B { 
    int field; 
}; 

struct G : A, B, C { 
    int field; 
}; 

int main() { 
    std::cout << _MSC_VER << std::endl; 
    std::cout << sizeof(E) << std::endl; 
    std::cout << sizeof(F) << std::endl; 
    std::cout << sizeof(G) << std::endl; 
    int o; 
    std::cin >> o; 
    return 0; 
} 

Jestem podane następujące dane wyjściowe:

1900 
4 
8 
8 

Dlaczego F i G mieć rozmiary 8 chociaż ich podstawy są puste? Dlaczego nie zwiększy się również rozmiar E?

Buduję to z Visual Studio Community 2015, wersja 14.0.25431.01 Aktualizacja 3. Wersja MSVC++ to najwyraźniej 9.0.

Jak to możliwe? Jakie są racjonalne uzasadnienia dla tak osobliwego układu pamięci?

+3

Dlaczego powinien to być błąd? Jaką regułę języka uważasz za niezgodną z kompilatorem? –

+0

@Kerrek Jeśli to nie jest błąd, ponieważ nie narusza standardu, to równie dobrze odpowiada na moje pytanie. –

+2

@KerrekSB Może nieformalna zasada "nie płacisz za to, czego nie używasz". Choć nie jest to zgodne ze standardem, martwiłoby mnie, gdybym myślał, że zostanie naruszony. – Brian

Odpowiedz

2

Aktualizacja 2 programu Visual Studio 2015 dodała obsługę funkcji Empty Base Class Optimization. Ponieważ jednak aktualizacje mają być kompatybilne z układem, optymalizacja nie jest domyślnie włączona; musisz ręcznie poprosić o to używając __declspec (empty_bases).

Jest więcej informacji w blogu VC: https://blogs.msdn.microsoft.com/vcblog/2016/03/30/optimizing-the-layout-of-empty-base-classes-in-vs2015-update-2-3/

to ostatecznie będzie domyślnym raz uwalniają one ważną aktualizację wersji kompilatora, gdzie są one dopuszczone do zerwania kompatybilności binarnej.

10

Nie istnieje żadna reguła językowa, która mówi, że każdy określony typ musi mieć konkretny rozmiar, z wyjątkiem char (rozmiar 1) i podlega ograniczeniu, że kompletne obiekty typu klasy mają niezerowy rozmiar. Nie ma nic ryzykownego w sposobie określania typów w twoim przykładzie przez konkretnego kompilatora.

Jeśli chodzi o nowe pytanie, po jego edycji: Możliwe, że MSVC nie wkłada dużego wysiłku w optymalizację dziedziczenia wielokrotnego, ponieważ jest to stosunkowo rzadka rzecz, z której można argumentować, że jest mało opłacalna. Nie wiem nic na temat prawdziwego procesu decyzyjnego, który się toczy, ale pomyślcie, że mogą istnieć pragmatyczne kompromisy inżynieryjne, takie jak te.

+0

Potrzeba pustej optymalizacji klasy bazowej została przywrócona wraz z wprowadzeniem [C++/WinRT] (https://github.com/Microsoft/cppwinrt). Jest dostępny od wersji Visual Studio 2015 Update 2, ale domyślnie jest wyłączony (jak wszystkie zmiany powodujące zerwanie zgodności binarnej). – IInspectable

Powiązane problemy