假设我们希望尽可能快地栅格化大量的线条,我们希望实际的绘图函数尽可能抽象,即我们需要的所有像素绘图函数,它们唯一共同点是他们的输入是像素坐标:
void plot(int x, int y);
像素绘图函数使用的参数在我们绘制大量线条之前设置,很少或从不更改。
第一个实施理念
我们的线条绘制功能可能看起来像
void raster_line(void (*plot)(int, int), int x0, int y0, int x1, int y1);
只要想要在(x,y)处绘制像素,该函数的实现就会调用plot(x,y)。大多数时候我们想要栅格到特定缓冲区,所以我们定义一个全局变量并让一个绘图函数作用于该缓冲区:
static int* buffer;
void plot(int x, int y) {
buffer[x + y * width] = 1;
}
因此,在调用raster_line之前,我们必须设置缓冲区变量,然后传递绘图函数指针。
第二个实施理念
我们的线条绘制功能可能看起来像
void raster_line(const AbstractPlot& ap, int x0, int y0, int x1, int y1);
其中AbstractPlot是接口
class AbstractPlot {
public:
virtual ~AbstractPlot() {}
virtual void plot(int x, int y) const = 0;
};
为了具有与第一个示例中相同的功能,我们提供了派生类
class Plot : public AbstractPlot {
public:
int* buffer;
void plot(int x, int y) const {
buffer[x + y * width] = 1;
}
};
因此,在调用raster_line之前,我们创建一个Plot对象,然后初始化缓冲区成员,然后传递实例。
摘要
我的测试说第一个想法比第二个想法快20%(虚函数表查找速度慢?)但我不喜欢我必须使用全局变量的事实。我对如何绘制线条感兴趣,但是如何使像素绘图尽可能通用(和快速)。有没有更好的方法来解决这个问题?
答案 0 :(得分:1)
使用 static 多态性可以避免不必要的虚拟调用开销,其中多态行为在编译时使用模板解析。这是大多数C ++标准库例如 std::sort
采用的方法。因此
template <class F>
void raster_line(F plot, int x0, int y0, int x1, int y1);
如果plot
是没有捕获的lambda函数,因此在实例化raster_line
时保证是无法使用的,那么在打开优化时根本就没有开销。如果绘图函数需要具有某种状态,则可以将其包装在functor类或带有捕获的lambda中,而不会对不需要访问任何状态的调用施加任何开销。
这种方法的主要缺点是raster_line
的定义必须放在标题中,并由包含标题的每个翻译单元编译。在这种特殊情况下,听起来运行时性能对您来说非常重要,因此接受编译时间的小幅增加可能是值得的权衡。但是你应该小心这样做无处不在,因为编译时间的增加可能是相当大的,而且运行时间的改善很小。