所以我在一大组对象上执行相同的功能。据我了解,最好将这组对象保存在连续的内存空间中以获得更好的时间。
std::vector<MyObject> myObjects;
// Fill vector with thousands of objects
for( auto const& obj listMyObjects ) { obj.doThing(); }
注意: myObjects
在应用程序的生命周期中存在并且不断变化。
在我的代码的其他部分,我想直接使用MyObject
的单个实例。通常我会用MyObjectManager
这样的类包装我的矢量并制作一个getter:
MyObject * obj = MyObjectManager::getObject( "OBJECT_NAME" );
obj->setName( "NEW_NAME" );
但这很容易出错,因为如果向量调整大小,指针可能会失效。这使我不得不使用索引或id,并通过管理器实现所有更改
int objId = MyObjectManager::getObject( "OBJECT_NAME" );
MyObjectManager::setObjectName( objId, "NEW_NAME" );
但我不认为这是最好的方式,因为它紧密地耦合了我的经理和对象类。所以我考虑为经理的朋友创建一个对象的接口:
class MyObject
{
std::string myName;
}
class MyObjectInterface
{
int myId;
MyObjectInterface( int id ) { myId = id; }
void setName( std::string name ) { MyObjectManager::myObjects.at( myId ).name = name; }
}
class MyObjectManager
{
friend class MyObjectInterface;
static std::vector<MyObject> myObjects;
static MyObjectInterface getObject( std::string name ) { return MyObjectInterface( myObjects.find( name ) ); // Psuedo code }
}
MyObjectInterface obj = MyObjectManager::getObject( "OBJECT1" );
obj.setName( "OBJECT2" );
注意:借口代码中的问题。这更像是关于代码的想法。
虽然这似乎有用,但我很好奇我是否正确地解释了这个问题以及这个解决方案是否过于复杂?我会喜欢一些见解,谢谢。
答案 0 :(得分:4)
我认为使用索引或id代替指针对于向量中的对象进行长期引用是合理的,原因在于您给出的原因。我认为将该id包装在类中以获得更多类型安全性也是合理的。
但我通常不会让该类成为真实对象的完整代理。如果vector
真的发生了变化,那么#{1}}会不断发生变化。从多个线程,然后甚至像
MyObjectManager::myObjects.at( myId ).name = name;
不安全。在使用at
获取对象的引用和设置名称之间,vector
可能已调整大小并且您的引用可能无效。
您通常需要在性能关键代码中有一些本地保证,vector
不会调整大小,使用引用或指针是安全的。在紧密循环中通过id查找对象的成本可能会超过您从数据位置获得的任何好处。
过度使用MyObjectInterface
可能会成为数据局部性的敌人,因为与MyObject
不同,它们不能保证在内存中是连续的。
如果实际上需要MyObjectInterface
和/或MyObjectManager
来提供复杂的同步机制,那么我建议您发布一个包含该问题的单独问题。