Расположение полей в памяти при наследовании

97
01 апреля 2022, 14:20

Рассмотрим следующий код:

struct A
{
    int i;
    float f;
};
struct B : A
{
    char c;
};

Подскажите, пожалуйста, есть ли гарантия того, что c располагается в памяти строго за f. Причем, точно таким же образом, как если бы эти члены изначально находились в одной структуре?

Также мне интересно, если B не будет являться POD типом, измениться ли что-то в расположении c в памяти?

Answer 1

Поля класса с одним уровнем доступа располагаются строго последовательно:

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 и в памяти.

Answer 2

Члены класса(структуры) конструируются и распологаются по такому же порядку, по которому они были объявлены( порядок иниуиализации не имеет значения). Значит, в структуре А, как сказано в 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

READ ALSO
Выравнивание структуры

Выравнивание структуры

Есть структура _dem_ram_data_Она должна занимать в памяти 16 байт, но я получаю 21 байт

97
QML не реагирует на изменения члена-класса C++

QML не реагирует на изменения члена-класса C++

Есть приложение с областью, которая реагирует на клик мышки:

105
Почему ошибка index out of range?

Почему ошибка index out of range?

Числовая последовательность называется пилообразной если каждый ее член (кроме первого и последнего) либо больше обоих своих соседей, либо...

96
Установка пустого атрибута ACCESS_EXTERNAL_DTD вызывает исключение "не поддерживается: http://javax.xml.XMLConstants/property/accessExternalDTD"

Установка пустого атрибута ACCESS_EXTERNAL_DTD вызывает исключение "не поддерживается: http://javax.xml.XMLConstants/property/accessExternalDTD"

Установка пустого атрибута ACCESS_EXTERNAL_DTD вызывает исключение "не поддерживается: http://javaxxml

71