2010-04-23 4 views
0

에서 유지 나는이 문제를 접근하는 방법을 잘 모르겠습니다 포인터 객체를 제거 총알을 발사하면이 목록에 추가됩니다. 또한 bullet 생성자 내부에서 동일한 객체에 대한 참조가 CollisionMgr에서 업데이트됩니다. CollisionMgr은 Bullet * 목록을 유지합니다.그 기준 세 가지 목록

Bullet::Bullet(GameGL*a_pGameGL, Player*a_pPlayer) 
: GameObject(a_pGameGL) 
{  
    m_pPlayer = a_pPlayer; 

    m_pGameGL->GetCollisionMgr()->AddBullet(this); 
} 

CollisionMgr.Update에서
class CollisionMgr 
{ 

void AddBullet(Bullet* a_pBullet); 

protected: 
std::list< Bullet*> m_BulletPList; 
} 

(); 어떤 조건에 따라 class Cell을 채우고 다시 Bullet * 목록을 포함합니다. 마지막으로 특정 조건에 따라 글 머리 기호를 삭제할 수있는 자격이 부여됩니다. 이제 이러한 조건은 셀의 목록을 반복하면서 테스트됩니다. 그래서,이 모든 장소에서 Bullet 객체를 삭제해야한다면, 더 이상 매달린 참조가 없도록 어떻게해야합니까?

std::list< Bullet*>::iterator bullet_it; 

    for(bullet_it = (a_pCell->m_BulletPList).begin(); bullet_it != (a_pCell->m_BulletPList).end(); bullet_it++) { 

     bool l_Bullet_trash = false; 
     Bullet* bullet1 = *bullet_it; 

     // conditions would set this to true 

     if (l_Bullet_Trash) 
      // TrashBullet(bullet1); 
      continue; 
     } 

또한, 나는 약 list::remove을 읽고 있었다, 그리고 그것이 우리가 삭제하려고하는 개체의 소멸자를 호출하는 것을 언급하고있다. 이 정보가 주어지면 한 목록에서 삭제하면 개체가 존재하지 않지만 목록에 여전히 참조가 포함되어있을 수 있습니다. 이러한 모든 문제를 어떻게 처리합니까?

답변

0

이 목록에는 글 머리 기호를 저장하지 않지만 글 머리 기호는 포인터로 저장하므로 소멸자가 호출되지 않습니다. 개체는 모든 목록에서 안전하게 제거 할 수 있지만 삭제를 직접 호출해야합니다.

3

하나의 옵션은 약한 참조와 함께 참조 카운팅을 사용하는 것입니다 (Boost는 이것을 지원합니다). 강력한 참조를 소유하는 "권한있는"컨테이너를 하나 가지고 있으므로 제거 된 불릿을 삭제합니다. 다른 모든 컨테이너는 약한 참조를 사용하고 약한 참조가 유효하지 않게 된 것을 발견하면 글 머리 기호를 제거합니다.

이 작업은 여러 곳에서 약간 복잡하지만 논리적으로 다른 메커니즘보다 훨씬 안전하고 안전합니다.

+0

다소 이해하지만 좀 더 구체적으로 알려주시겠습니까? 검색에 좋은 키워드는 무엇입니까? – brainydexter

+0

Boost [shared_ptr and weak_ptr] (http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/smart_ptr.htm)를 살펴보십시오. –

0

재미있는 관찰 또는 아마도 이것은 '정의되지 않은 동작'의 일부일뿐입니다. 그래서,이 내가 총알을 부수고하고 그 나에게 지금의 error..as 포기하지 않을 방법이다 : 나는 목록에서 총알에 대한 참조를 "제거"일단, 그래서

void CollisionMgr::TrashBullet(Bullet* a_pBullet, Cell* a_pCell) 
{ 

    a_pBullet->Owner()->TrashBullet(a_pBullet); 
    m_BulletPList.remove(a_pBullet); 
    //a_pCell->m_BulletPList.remove(a_pBullet); 

    delete a_pBullet; 
} 

을, 나는 수동으로 삭제 그것. 나 한테 무슨 혼란 것은,의 설명에서 '목록 :: 제거'

void remove (const T& value); 가 특정 값을 가진 요소를 제거합니다. 특정 값을 가진 모든 요소 을 목록에서 제거합니다. 이 개체의 소멸자가 호출되고 은 요소를 제거한 후 요소의 목록 크기를 줄입니다.

따라서 목록에서 글 머리 기호를 호출하면 해당 글 머리 기호 개체의 소멸자가 호출되어야합니다. 하지만, 여기에 그 일이 일어나지 않습니다 ... 이것은 정의되지 않은 동작과 컴파일러의 특질 중 일부입니까? 아니면 여기에 사소한 것을 놓치고 있습니까?

+0

아니요, 소멸자를 호출하면 안됩니다. 목록에서 글 머리 기호에 대한 포인터를 제거하고 있습니다. 객체에는 소멸자가 있지만 포인터는 그렇지 않습니다. –

+0

포인터가 동적으로 할당 된 객체를 가리키는 경우, delete를 호출하는 것은 사용자의 책임입니다. 단 하나의 포인터 만 사용해야합니다. –

+1

컨테이너에 포함 된 * 포인터 *가 소멸됩니다. 이는 제공된 인용 부호가 나타내는 것입니다. 포인터가 가리키는 것은 자동으로 소멸되지 않습니다. 포인터에서 삭제 된 것을 정확히 한 번 호출해야합니다. 더 쉽게 스마트 포인터를 사용하여 관리 할 수 ​​있습니다. –

관련 문제