Мне сказали, что если я делаю наследование, когда базовый класс содержит защищенные переменные-члены, а дочерний класс создает базовый класс, он дублирует свои члены в памяти.... он выделит в 2 раза больше памяти для m_sound
и m_age
.
Нет.В вашем примере каждый объект типа Dog
содержит только два подобъекта int
и один подобъект типа std::string
.Технически компилятору будет разрешено использовать больше памяти, чем необходимо, но для этого не будет никаких причин, и программе не будет разрешено иметь разные адреса для одного и того же члена или несколько вызовов конструктора или деструктора std::string
.
Не зная вашего источника, больше ничего не скажешь об этом.
Что именно распределяется в памяти, где отмечаются вопросы между данными родительского класса и потомком?
Подробности зависят от вашего компилятора и стандартной библиотеки, но, скорее всего, все или большинство байтов между тем, что вы определили как m_age
и m_speed
, принадлежат подобъекту члена std::string m_sound
.То есть, я предполагаю, что если бы вы сделали std::cout << sizeof(std::string) << "\n";
, вы бы получили 28 или близко к нему.
Из-за того, как работает объектная модель C ++, sizeof(std::string)
является константой, и каждый std::string
получает только фиксированное количество байтов, но строка может «содержать» много символов.Обычно это означает, что std::string
имеет указатель char*
на динамически распределенную память, которая содержит фактические символы.В общем случае также потребуется способ узнать длину строки и емкость динамически размещенного буфера.
Но, как вы заметили, символьные значения вашей строки фактически появляются в памяти std::string
объект напрямую, что, вероятно, означает, что ваша стандартная реализация библиотеки использует Small String Optimization : std::string
может содержать либо указатель char*
, длину и емкость, либо определенное количество символьных значений напрямую.(Это может уменьшить потребность в динамическом выделении и освобождении памяти, что может занять много процессорного времени, если используется достаточно часто.) std::string
также потребуется некоторый способ узнать, находится ли он в данный момент в режиме указателя или в режиме прямого хранения, иэта информация предположительно где-то в более поздних байтах.
Чтобы точно определить, что означает каждый байт в std::string
, вам нужно будет найти определение шаблона класса std::basic_string
в заголовочных файлах, используемых вашимкомпилятор.