我的entityManager中有以下代码。
void GameObjectManager::updateAll(float frametime)
{
checkAlive();
// iterate through the entityManager, updating each entity and then adding it into the quadTree.
for (auto itr = _gameObjects.begin(); itr != _gameObjects.end(); itr++)
{
itr->second->Update(frametime);
tree->AddObject(itr->second);
}
// iterate once again through the entityManager but this time checking itself against the quadTree.
for (auto x = _gameObjects.begin(); x != _gameObjects.end(); x++)
{
std::vector<std::unique_ptr<Entity>> returnObjects = tree->GetObjectsAt(x->second->GetPosition().x, x->second->GetPosition().y );
for ( int n = 0; n < (int)returnObjects.size(); n++ )
{
std::unique_ptr<Entity>& collided = returnObjects[n];
if(object->getEntityName() != collided->getEntityName())
{
if(object->GetBoundingRect().intersects(collided->GetBoundingRect()))
{
object->Touch(collided);
}
}
}
}
tree->Clear();
}
在这个例子中,智能指针的正确用法是什么?当我将实体添加到四叉树时,我应该创建一个shared_ptr,将其作为引用传递或使用std :: move?我倾向于前两个中的一个,因为移动指针的所有权会将它从std :: map移动,这是我不想做的事情。
在传递信息时,是否应遵循简单的规则?我应该何时使用引用,何时应该使用shared_ptr?
答案 0 :(得分:1)
当使用所有权语义时,我使用以下基本方法来引用。
将quadTree
更改为接受和返回引用而不是强指针似乎违反了这两条规则。这没关系,但需要进行额外的更改。在您的情况下,quadTree
是一个成员变量。如果发生异常,quadTree
仍将包含对其不拥有且可能不再存在的对象的引用。这可以通过使用调用函数范围的quadTree
本地来轻松纠正。这样可以保证quadTree
的有效期不长于_gameObjects
- 实际所有者。
这只是扩展了第一条规则,以包含函数所属对象的生命周期。这些更改可能看起来像这样(使用指针而不是可以应用相同的引用)。
void GameObjectManager::updateAll(float frametime)
{
checkAlive();
quadTree tree;
// iterate through the entityManager, updating each entity and then adding it into the quadTree.
for (auto itr = _gameObjects.begin(); itr != _gameObjects.end(); itr++)
{
itr->second->Update(frametime);
tree.AddObject(itr->second.get());
}
// iterate once again through the entityManager but this time checking itself against the quadTree.
for (auto x = _gameObjects.begin(); x != _gameObjects.end(); x++)
{
std::vector<Entity*> returnObjects = tree->GetObjectsAt(x->second->GetPosition().x, x->second->GetPosition().y );
for ( int n = 0; n < (int)returnObjects.size(); n++ )
{
Entity* collided = returnObjects[n];
if(object->getEntityName() != collided->getEntityName())
{
if(object->GetBoundingRect().intersects(collided->GetBoundingRect()))
{
object->Touch(collided);
}
}
}
}
//tree.Clear(); // Called by destructor.
}