Оптимизация вызова виртуальной функции

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

// Base.h
class Base
{
public:
virtual void Foo() = 0;
};

// Concrete.h
class Concrete : public Base
{
public:
virtual void Foo()
{
// do something;
}
};

//Some.h
extern Base* const g_object;

// Some.cpp
Concrete on_stack_concrete;

Base* const g_object = &on_stack_concrete;

Предполагается, что хитрость заключается в использовании константного указателя на переменную, которая выделяется в стеке (не динамически), и что компилятор наверняка оптимизирует это. Поэтому всякий раз, когда пользователь вызывает g_object-> Foo (), часть // выполнения чего-либо будет выполнена без необходимости поиска в v-таблице.

Это правда или нет?

Заранее спасибо за любой повтор.

РЕДАКТИРОВАТЬ:

Возможное использование такой конструкции заключается в ограничении интерфейса конкретных реализаций. Конечно, можно утверждать, что «ограниченные» методы должны быть закрытыми, но иногда другим модулям библиотеки требуется доступ к этим общедоступным дополнительным методам объекта, не позволяя пользователю манипулировать ими. Так, например, используя #defines, можно создать код, подобный следующему:

// Some.cpp
#ifdef _WIN32
Win32Concrete concrete;
#elif defined _UNIX
UnixConcrete concrete;
#endif

Base* const g_global = &concrete;

Фактически объявление этих классов может быть определено только в файле CPP, поэтому пользователь не знает об их существовании.

Вопрос не Зачем в первую очередь использовать такой константный указатель, но если это возможно, оптимизировать поиск в v-таблице в таком сценарии.

3

Решение

Вы, кажется, неправильно используете virtual,

virtual реализует полиморфизм во время выполнения. И сценарий, который вы описываете, не использует или не нуждается в этом. Вряд ли оба Win32Concrete а также UnixConcrete существуют в любой среде компиляции.

Вместо:

// Some.cpp
#ifdef _WIN32
Win32Concrete concrete;
#elif defined _UNIX
UnixConcrete concrete;
#endif

Base* const g_global = &concrete;

использовать:

// CommonHeader.h
#ifdef _WIN32
typedef Win32Concrete Concrete;
#elif defined _UNIX
typedef UnixConcrete Concrete;
#endif

Теперь ваши функции не должны быть виртуальными.

4

Другие решения

Самый простой способ решить эту проблему — создать классы, которым нужен доступ к ограниченному методу, друзей класса Concrete. Затем они получают полный доступ к классу, а все остальные получают только публичный доступ.

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

class Concrete
{
public:
void foo() { ... }
protected:
void bar() { ... }
};

class ConcretePrivate : public Concrete
{
public:
void bar() { Concrete:: bar(); }
};

ConcretePrivate g_globalPrivate;
Concrete& g_global = g_globalPrivate;

Код, который использует g_global может получить доступ только к конкретным методам. Код, который использует g_globalPrivate может получить доступ к методам ConcretePrivate.

1

Этот подход используется в исходном коде Doom 3 (https://github.com/id-Software/DOOM-3-BFG/), например, neo / framework / FileSystem.h определяет это:

extern idFileSystem *       fileSystem;

И neo / framework / FileSystem.cpp определяет это:

idFileSystemLocal   fileSystemLocal;
idFileSystem *      fileSystem = &fileSystemLocal;

Единственное обсуждение, которое я мог найти об этом: http://fabiensanglard.net/doom3/

Все объекты высокого уровня idTech4 — это абстрактные классы с виртуальными методами. Обычно это связано с падением производительности, поскольку каждый виртуальный адрес метода должен быть найден в виртуальной таблице перед вызовом во время выполнения. Но есть «хитрость», чтобы этого избежать.

Поскольку объект, размещенный статически в сегменте данных, имеет известный тип, компилятор может оптимизировать поиск в vtable при вызове методов commonLocal.

1
По вопросам рекламы [email protected]