Является ли в C++ "открытый тип int без знака" в базовом классе более быстрой альтернативой dynamic_cast?
В C++ медленная "dynamic_cast" является известным фактом. Я подумал о следующем простом способе узнать тип объекта в иерархии. Может кто-нибудь объяснить, может ли это быть медленнее, чем dynamic_cast? А если нет, то почему это не является обычной практикой, учитывая, что скорость является худшим недостатком C++ по сравнению с C?
struct Base {
unsigned m_type;
Base(unsigned type): m_type(type) {}
Base(): m_type(0) {}
};
struct Derived1: Base {
Derived1(): Base(1) {}
Derived1(int type): Base(type) {}
};
struct Derived2: Base {
Derived2(): Base(2) {}
};
struct Derived3: Derived1 {
Derived3(): Derived1(3) {}
};
void my_func(Base * p) {
if (p - > m_type == 0) {}
else if (p - > m_type == 1) {}
else if (p - > m_type == 2) {}
else if (p - > m_type == 3) {}
}
2 ответа
Может кто-нибудь объяснить, может ли это быть медленнее, чем dynamic_cast?
Это может быть медленнее, чем dynamic_cast'ing, когда...
- компилятор может выяснить, из чего вы используете dynamic_cast, и, таким образом, избежать каких-либо действий для динамического приведения.
Base
-приобретенные объекты являются неизменяемыми, что позволяет выполнять все виды оптимизации, в то время как ваши классы содержат переменную изменяемого типа.- у вас большая и сложная иерархия типов, поэтому у вас есть много сравнений.
Кроме того, вы действительно проверили, насколько медленный динамический_каст относительно других вещей, которые вы могли бы делать?
Почему это не распространенная практика [?]
- Поскольку это делает код более сложным, добавляет непреднамеренную потенциальную семантику и возможности и идет вразрез с основными механизмами абстракции языка.
- Потому что это требует, чтобы базовый класс знал обо всех своих производных классах (или иначе вы по сути переопределяете динамическое приведение).
- Потому что это делает некоторые части специфичного для класса кода локальными для определения класса, а другие части специфичного для класса кода - локальными для базового класса.
... учитывая, что скорость является худшим недостатком C++ по сравнению с C?
Это не так. В наши дни вполне возможно (и часто) писать более эффективный код на C++, чем семантический эквивалент на C.
Но в любом случае это не должно иметь значения, поскольку у вас нет бизнеса, выполняющего динамическое приведение кода, критичного к производительности; это недостаток дизайна, как предлагает @NathanOliver в комментарии.
В C++ медленная "dynamic_cast" является известным фактом.
Это был известный факт тридцать лет назад (когда я впервые начал использовать компиляторы C++) 1989/1990 (тогда я использовал любой компилятор, установленный по умолчанию на рабочих станциях Sun). НО это больше не относится к современным компиляторам.
Я не забываю загружать g++ (я думаю, 2.4; ок. 1996-1998), чтобы посмотреть, что происходит (см. Ниже). Компилятор (g++) будет проходить по иерархии классов и на каждом уровне будет выполнять сравнение строк с именами классов при поиске правильной записи типа. Это было сделано, поскольку каждый модуль компиляции потенциально имел свой собственный уникальный набор записей типа (так что вы не могли просто сравнивать указатели).
А если нет, то почему это не обычная практика?
В результате многие люди действительно написали свои собственные версии динамического приведения для повышения скорости (но опять же люди все еще пытались понять, как написать хороший C++ в те дни, и большая часть кода была написана как C, так что производительность, вероятно, не была ошибка в динамической трансляции). Но пара реализаций, которые я видел, была чрезвычайно хрупкой и содержала множество ошибок. Вот почему я посмотрел, как работает g ++. К этому времени (1998) самописный динамический состав, который использовала моя компания, показывал свой возраст, и я разорвал его, чтобы использовать версию компилятора (никаких измеримых изменений производительности, но множество таинственных ошибок исчезло).
К счастью, это было исправлено давно. До конца прошлого века (я не могу дать вам точную дату). Но определенно до g++ 3.0.
Я подумал о следующем простом способе узнать тип объекта в иерархии.
Вы определили класс по номеру. Это не то же самое, что актерский состав. Вам все еще нужно преобразовать указатель в правильное местоположение.
Может кто-нибудь объяснить, может ли это быть медленнее, чем dynamic_cast?
Я подозреваю, что вам будет трудно написать версию быстрее, чем текущая реализация. Особенно учитывая все особые угловые случаи с виртуальным наследованием и тому подобное. Если честно, я сомневаюсь, что вы могли бы сделать быстрее даже для простой иерархии, как вы показываете. У компилятора есть 30-летние приемы оптимизации. Эти приемы применяются во время компиляции, а ваш результат - во время выполнения.
учитывая, что скорость является худшим недостатком C++ по сравнению с C?
Мне трудно в это поверить. У вас есть цитата?