Рассмотрим следующий код:
struct A
{
int i;
float f;
};
struct B : A
{
char c;
};
Подскажите, пожалуйста, есть ли гарантия того, что c располагается в памяти строго за f. Причем, точно таким же образом, как если бы эти члены изначально находились в одной структуре?
Также мне интересно, если B не будет являться POD типом, измениться ли что-то в расположении c в памяти?
Поля класса с одним уровнем доступа располагаются строго последовательно:
12.2 Class members [class.mem]
18 Non-static data members of a (non-union) class with the same access control (Clause 14) are allocated so that later members have higher addresses within a class object. The order of allocation of non-static data members with different access control is unspecified (Clause 14).
Расположение базовых подъобъектов неспецифицировано:
13 Derived classes [class.derived] 5 The order in which the base class subobjects are allocated in the most derived object (6.6.2) is unspecified.
Однако для standard-layout классов адрес объекта обязательно совпадает с адресом первого поля и / или с адресом первого подъобъекта:
12.2 Class members [class.mem] 25 If a standard-layout class object has any non-static data members, its address is the same as the address of its first non-static data member. Otherwise, its address is the same as the address of its first base class subobject (if any).
Из этого всего следует, что с в классе B не обязательно будет располагаться за f так как класс B не является standard-layout классом, а вот если бы оно было объявлено после f в классе A, то тогда было бы обязательно расположено строго после f и в памяти.
Члены класса(структуры) конструируются и распологаются по такому же порядку, по которому они были объявлены( порядок иниуиализации не имеет значения). Значит, в структуре А, как сказано в 12.2 Class members [class.mem], приведенной user7860670, элементы обьекта будут распологаться строго по порядку:
обьект A() -> | i | f |
Тут адрес A() совпадает с адресом i , как сказано в 12.2 Class members [class.mem] 25 .
Обьекты типа В, будут иметь один подобьект базового класса А, это значит, что на его основании лежит объект А() + у него еще есть член char c, который расположится после обьекта А().
обьект В() -> | A() | c |
Это значит, что с, в классе В, в данном случаи, обязательно будет распологаться после f
обьект В() -> | i | f | c |
Но, если есть наиболее производный обьект (most derived object), например:
struct D {
int m{};
};
struct most_derived : D, B {};
most_derived md_obj;
который имеет подобьект типа А, подобьект типа В(который в свою очередь имеет подобьект типа А) и подобьект типа D
И вот тут : порядок расположения подобьектов (D() и В()), в наиболее производном обьекте ( md_obj ) для базового класса А, не определен,следовательно в обьекте md_obj порядок следования m и с, не определено(в частности &md_obj будет совпадать с &m или с &i ?... неизвестно) _ вот о чем говорится в
13 Derived classes [class.derived] 5
.
Вывод: если В является не POD типом, расположение с всеравно не изменится, оно может изменится только в другом не POD типе _ таком, как most_derived
Продвижение своими сайтами как стратегия роста и независимости