我正在编写一些通用代码,它们基本上将有一个由一组控制器更新的对象向量。
该代码在我的特定上下文中有点复杂,但简化为:
template< class T >
class Controller
{
public:
virtual ~Controller(){}
virtual void update( T& ) = 0;
// and potentially other functions used in other cases than update
}
template< class T >
class Group
{
public:
typedef std::shared_ptr< Controller<T> > ControllerPtr;
void add_controller( ControllerPtr ); // register a controller
void remove_controller( ControllerPtr ); // remove a controller
void update(); // udpate all objects using controllers
private:
std::vector< T > m_objects;
std::vector< ControllerPtr > m_controllers;
};
我故意不使用 std::function 因为我不能在我的特定情况下使用它。我还故意使用共享指针而不是原始指针,这实际上对我的问题并不重要。
无论如何,我感兴趣的是 update() 实现。我可以通过两种方式做到这一点。
A)对于每个控制器,更新所有对象。
template< class T >
void Group<T>::update()
{
for( auto& controller : m_controllers )
for( auto& object : m_objects )
controller->update( object );
}
B)对于每个对象,通过应用所有控制器进行更新。
template< class T >
void Group<T>::update()
{
for( auto& object : m_objects )
for( auto& controller : m_controllers )
controller->update( object );
}
“测量!测量!测量!” 你会说,我完全同意,但我无法衡量我不使用的东西。问题是它是通用代码。我不知道T的大小,我只是假设它不会很大,也许很小,也许还是有点大。真的,除了它被设计为包含在向量中之外,我不能对 T 做出太多假设。我也不知道将使用多少个控制器或 T 个实例。在我目前的用例中,会有很大不同的计数。
问题是:一般来说哪种解决方案最有效?
我在这里考虑缓存一致性。此外,我假设此代码将用于不同的编译器和平台。
我的直觉告诉我,更新指令缓存肯定比更新数据缓存更快,这将使解决方案 B) 通常更有效。但是,当我对性能产生怀疑时,我学会了不相信自己的阵风,所以我在这里问。
我得到的解决方案将允许用户选择(使用编译时策略)哪个更新实现与每个 Group 实例一起使用,但我想提供一个默认策略,我无法决定哪个是在大多数情况下最有效。