2013-04-14 8 views
1

У меня есть следующий фрагмент кода в моем 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?

ответ

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. 
} 
Смежные вопросы