Почему пустая оптимизация базового класса не работает?
Почему пустая оптимизация базового класса (EBO) не полностью применяется в Visual С++?
Если у меня много базовых классов, есть ли способ помочь компилятору сделать эту оптимизацию?
#include <iostream>
struct T1 { };
struct T2 { };
struct T3 { };
struct T4 { };
struct T5 { };
struct T6 { };
struct Test : T1, T2, T3, T4, T5, T6 { };
int main() { std::cout << sizeof(Test); } // Prints 5
Ответы
Ответ 1
Это давняя ошибка в компиляторе Visual С++. Когда класс происходит из нескольких пустых базовых классов, только исходный пустой базовый класс будет оптимизирован с использованием пустой оптимизации базы (EBO).
Об этой проблеме сообщалось в Microsoft Connect в 2006 году: Пустая оптимизация базы данных не работает должным образом. В настоящий момент старые ошибки не отображаются в Microsoft Connect. Мне сказали, что это временная проблема, хотя я не знаю, когда она будет решена. В то же время, следующий ответ на ошибку от Jonathan Caves, который является одним из разработчиков в команде компилятора Visual С++:
Привет: к сожалению, несмотря на то, что это ошибка в объектной модели Visual С++, мы не можем ее исправить в это время, учитывая, что это исправление потенциально может сломать многие существующие программы по мере изменения размеров объектов. Надеемся, что в будущем мы сможем решить эту проблему, но не для следующей версии продукта.
Спасибо за сообщение о проблеме.
Ответ 2
"Официальная" позиция - MSVC будет выполнять только EBO для одиночного наследования, к сожалению, отчет об ошибке, где это указано, был удален MS, поэтому все, что остается, - это более старый вопрос о MSDN, который указывает на это и ссылается на отчет об удаленной ошибке.
Ответ 3
Начиная с Visual Studio 2017 Update 2, это исправлено... но по умолчанию оно отключено. И вы должны явно включить его для каждого класса отдельно:
struct __declspec(empty_bases) Test : T1, T2, T3, T4, T5, T6 { };
// ^^^^^^^^^^^^^^^^^^^^^^^
static_assert(1 == sizeof(Test));
К сожалению, это по-прежнему верно даже для /std:c++latest
и /permissive-
даже в Visual Studio 2019: не существует способа установить его глобально.