Empty base optimization



В этом посте мы рассказали, о том, сколько весит объект пустого класса. Настоятельно рекомендую вернуться к этому посту, чтобы быть в контексте.



Теперь возникает вопрос: что будет, если мы отнаследуемся от пустого класса? Каким образом будет учитываться этот один байт в наследнике и где он будет расположен?



Вообще говоря, ненулевой размер объекта пустого класса нужен просто для нормальной его адресации. Никакой полезной нагрузки он не несет и нужен, чтобы "просто работало". Однако, когда мы наследуется от такого класса, и, например, размещаем в наследнике какие-то поля, то наследник уже не нуждается в фейковом байте, чтобы нормально работать. У него это и так получится прекрасно. Получается, что этот 1 байт будет, как жабры на теле млекопитающего: предкам были нужны, а сейчас вообще ни к селу, ни к пгт.



Поэтому есть такое понятие, как empty base class optimization. Если мы наследуемся от пустого класса, то размер класса наследника будет ровно таким же, как как будто бы он ни от чего не наследовался.



Пример:



struct EmptyClass {

void MethodMeantJustNotToLeaveClassDeadInside() {}

};



struct Derived : public EmptyClass {

int a;

char b;

double c;

};



struct SizeReference {

int a;

char b;

double c;

};



int main() {

EmptyClass a;

Derived b;

SizeReference c;

std::cout << "EmptyClass object size: " << sizeof(a) << std::endl;

std::cout << "Derived object size: " << sizeof(b) << std::endl;

std::cout << "SizeReference object size: " << sizeof(c) << std::endl;

}





Вывод консоли:



EmptyClass object size: 1

Derived object size: 16

SizeReference object size: 16





Вроде бы очень логичная штука и даже почти интуитивная штука, но немногие знают в ее в профиль и анфас, поэтому сегодня исправили этот момент)



Optimize your life. Stay cool.



#cppcore #optimization