У меня есть два предложения по устранению вызовов виртуальных функций, если это необходимо для повышения производительности. Для иллюстрации предположим, что у вас есть функция, принимающая указатель на функцию в качестве аргумента:
void my_algorithm(int (*func)(...), ...)
{
/* ... */
}
Также предположим, что вы заранее знаете все возможные значения, которые может принимать указатель на функцию. Например:
my_algorithm(func_1, ...);
//...
my_algorithm(func_2, ...);
Сначала преобразуйте исходный my_algorithm() в макрос:
#define MY_ALGORITHM(func, ...) \
{ \
/* ... */ \
}
Затем перепишите my_algorithm() как:
extern int func_1(...);
extern int func_2(...);
void my_algorithm(int (*func)(...), ...)
{
if (func == func_1)
MY_ALGORITHM(func_1, ...)
else if (func == func_2)
MY_ALGORITHM(func_2, ...)
else
assert(0 && "Unexpected function arg to my_algorithm()");
}
Это, конечно, удвоит размер скомпилированного объектного файла. И, на первый взгляд, он устраняет только один уровень косвенности. Но если func_1 и/или func_2 встроены, вы можете получить значительное ускорение.
И вы даже можете «передавать» макросы, например:
#define HYPOT_Y(x) hypot(x, y)
MY_ALGORITHM(HYPOT_Y, ...); //assumes y is known
Второе предложение представляет собой вариант этого с использованием макросов X ( http://en.wikipedia.org/wiki/C_preprocessor#X-Macros). Вместо #define поместите тело исходного my_algorithm() в отдельный файл my_algorithm.h. Затем перепишите my_algorithm() как:
void my_algorithm(int (*func)(...), ...)
{
if (func == func_1)
#define func func_1
#include "my_algorithm.h"
#undef func
else if (func == func_2)
#define func func_2
#include "my_algorithm.h"
#undef func
else
assert(0 && "Unexpected function arg to my_algorithm()");
}
Я бы, наверное, использовал X-макросы, если код больше пары десятков строк. Его преимущества включают (без каламбура):
- Нет уродливых обратных косых черт
- Упрощенная отладка (например, обратная трассировка и пошаговое выполнение).
Это все стандартный C. Но скорее олдскульный.
person
Joseph Quinsey
schedule
06.05.2010