5

出于性能原因,我使用Curiously Reoccuring Template Pattern来避免虚函数。我有很多执行数百万次的小命令。我正在尝试将其融入命令模式。我想将大量命令添加到队列中,然后逐个遍历它们执行。每个命令都使用 CRTP 来避免虚拟功能。我遇到的问题是命令模式通常是使用指针向量实现的。但是,当 Command 类被模板化后,就很难传递通用的 Command 指针。我不是 C++ 专家,所以也许有一种明显的方法来存储模板化命令对象的向量?我一直在尝试使用类似的东西:

boost:ptr_vector commands;
AddCommand(Command* command) {
  commands.push_back(command);
}

问题Command不是类型,所以Command* command会出现编译错误。我需要使用Command<CommandType>,但这不起作用,因为我需要队列来保存不同类型的命令。

任何解决方案的想法?还是虚拟功能是我唯一的选择?

添加:命令对象是蒙特卡罗模拟算法的一部分。所以你可能有,Command 是来自正态分布的随机数,其中正态分布的参数是类的一部分。所以命令模式非常适合。我有很多按特定顺序调用需要维护状态的函数。

4

3 回答 3

12

CRTP 通过在编译时解析对象的运行时类型来发挥它的魔力,以便编译器可以内联函数调用。如果您有一个指向泛型类型的指针向量,编译器将无法确定具体的具体类型,也无法进行编译时解析。

仅从您在问题中获得的信息来看,我认为虚函数是您的最佳选择。然而,虚函数并没有那么慢。当然,它们比内联函数慢,但在许多情况下它们足够快!特别是如果您的进程受限于 I/O 时间而不是处理时间。

这个问题的答案之一这个问题进行了更深入的讨论。总而言之,虚函数调用的开销可能以纳秒为单位。它比这更复杂,但关键是你不应该害怕虚函数,除非你的函数正在做一些非常微不足道的事情,比如单个赋值。您说您的命令很小,所以也许是这样。我会尝试用虚拟功能做一个快速原型,看看是否能提供可接受的性能。

于 2009-06-11T00:27:54.257 回答
2

除非您在编译期间构建命令队列,否则您想要的是不可能的。

于 2009-06-11T00:33:31.360 回答
1

我不知道您的命令队列是经常更改还是很少更改。

如果它很少改变,与它的执行频率相比,在我看来这可能是代码生成的工作。

只需打印出一个程序来执行您需要的操作,即时编译和链接一个 dll,然后加载它。这应该需要大约一秒钟。没有类、对象或调度。而且,如果您单步执行,您将看到几乎没有对您的答案没有实质性贡献的周期。

于 2009-06-12T11:24:17.470 回答