Статические функции против виртуальных функций с точки зрения скорости - PullRequest
0 голосов
/ 02 марта 2012

У меня проблемы. При планировании своей программы я рассматриваю 2 версии:

  1. Использование статических методов в классах с дополнительным параметром (указатель на копию класса).
  2. Использовать виртуальные методы (vtable)

Что быстрее? Почему?

Редактировать: Мне нужно сделать следующий алгоритм: массив должен хранить указатели на метод разных классов (они соответствуют разным игровым объектам), например, метод Draw ().

Основная задача - хранение и вызов методов разных классов.

Ответы [ 2 ]

2 голосов
/ 02 марта 2012

В этот момент вам, вероятно, вообще не следует думать о микрооптимизациях - сосредоточьтесь на выборе эффективных алгоритмов, а также на ясности и корректности кода; затем определите любые узкие места, которые мешают ему работать должным образом. Сказав это, вот некоторые мысли о маловероятном случае, когда вы обнаружите, что виртуальная отправка становится проблемой.

Два не эквивалентны - первый (если я понимаю, что вы говорите) пытается эмулировать не виртуальную функцию путем явной передачи this -подобного указателя на статическую функцию и, вероятно, будет точно так же быстро, как и нестатический эквивалент. Он будет вести себя иначе, чем виртуальная функция, и поэтому не может использоваться, если вам нужна виртуальная диспетчеризация.

Не виртуальная функция (почти наверняка) будет немного быстрее, чем виртуальная функция - она, скорее всего, будет встроенной, и если она не встроена, ее можно вызывать напрямую, а не искать во время выполнения. Поэтому объявляйте функции виртуальными только тогда, когда вам нужна виртуальная диспетчеризация.

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

0 голосов
/ 02 марта 2012

Во-первых, виртуальные функции и то, что вы предлагаете, имеют разную семантику.Если вам нужно другое поведение, потому что у вас разные типы объектов, то вряд ли вы сможете добиться большего успеха, чем реализация виртуальных функций компилятором.Если вам это не нужно, просто не объявляйте функцию виртуальной.

И не беспокойтесь о проблеме производительности, пока не узнаете, что она одна.

Если после полученияРаботая с кодом, вы обнаруживаете проблемы с производительностью из-за вызовов виртуальных функций (обычно из-за того, что компилятор не может встроить функцию, поэтому вы теряете все оптимизации, которые следуют за встраиванием), вы можете, пунктуально, избежать затрат на виртуальные функцииесли вы правильно оформите класс.Предположим, что рассматриваемая функция имеет вид f():

class Base
{
    virtual void doF() = 0;
public:
    void f() { doF(); }
};

class Derived : public Base
{
    virtual void doF() { f(); }
public:
    void f() { /* ... */ }
};

Если вы делаете это, и у вас есть, например, узкий цикл, где вы постоянно вызываете f() для одного и того же объекта, вы можетесделать что-то вроде:

void
tightLoop( Base& object )
{
    Derived& o = dynamic_cast<Derived&>( object );
    for ( /* ... */ ) {
        o.f();
    }
}

Если вы сделаете это, конечно, tightLoop может быть вызван только с объектом, который на самом деле Derived.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...