2012-09-12 3 views
2

C++에서 비교적 큰 프로젝트를 작성 중이며 객체 삭제에 문제가 있습니다. 이 프로젝트는 정확히는로 거의 같은 게임입니다.C++ 안전한 객체 삭제

나는 게임에서 모든 괴물 인 종류 Npc가있다. 그것들은 관리 (로딩, 저장, 생성, 삭제 등)를 담당하는 별도의 클래스 Storage<Npc>에 생성되어 저장됩니다. 몬스터가 죽을 때마다 해당 오브젝트 npc을 완전히 파괴하고 파괴해야합니다. 객체 자체를 삭제하는 것은 문제가 아니며 Storage<NPC>에서 메소드를 호출했습니다. 문제는 코드에이 포인터가 이미 많이 있음을 의미합니다. npc은 유효하지 않으며이를 사용하려고하면 많은 문제가 발생합니다. 예 :

  1. 그가 죽기 전에 수행 할 작업이있을 수 있습니다.
  2. 그는 레코드 저장소에 포인터를 올려 놓았습니다.
  3. 그는 누군가를 괴롭히는 것과 같은 지속적인 활동에 참여했을 수도 있습니다.

코드에는 이러한 포인터가 많이 있으므로 추적하기가 거의 불가능합니다. 내가 필요한 것은 npc이 이미 죽었고 그 주소에 실제 객체가 저장되어 있지 않기 때문에이 포인터를 가지고있는 코드 부분이 그의 죽음에 적절하게 반응 할 수 있도록하는 것입니다.

나 자신은 몇 가지 아이디어왔다,하지만 그들 중 지금까지 아무도 나에게 정말 좋은 것 같다 :이 같은 주소에 물체가있는 경우 내가 Storage<NPC> 클래스를 요청할 수

  • . 잠재적 인 문제는 개체 삭제 후 다른 개체가 같은 주소에 할당되어 버그가 발생할 수 있다는 것입니다.
  • 유효하지 않은 포인터를 사용할 수있는 모든 위치를 알릴 수 있습니다. 그러한 위치의 수가 시간이 지남에 따라 증가하고 이것이 일을하는 것이 고통이기 때문에 나쁜 생각입니다.
  • 스마트 포인터의 일부 버전을 구현할 수는 있지만 사용하려는 버전이 확실하지 않습니다.

TL; DR 버전 : 나는 객체에 대한 포인터 포인트 경우 말해 것이다 솔루션이 필요하거나 메모리 무료 덩어리를 가리키는 또는 다른 개체를 원래 개체 삭제 후 할당 .

+0

메모리가 해제/무효화 될 때마다이를 'nullptr'로 설정하는 방법은 무엇입니까? : P – SingerOfTheFall

+0

이미 질문에 대답으로 태그를 지정했습니다. 스마트 포인터를 사용하십시오. std :: shared_ptr을 사용하는 것이 좋습니다 – stefan

+0

@SingerOfTheFall, 당신이 말하려고하는 것은'delete pnpc;를 할 때마다'pnpc = 0;'을해야한다는 것입니다. 그러나 'pnpc'와 같은 다른 포인터가 프로그램의 다른 곳에 저장되면 t 0으로 설정되지 않으므로 작동하지 않는 것으로 보입니다. – Saage

답변

2

약 포인터를 사용하는 것은 어떻습니까? std::shared_ptr (C++ 11, C++ 03의 경우 std::tr1::shared_ptr 사용)에 Npc을 저장하면 shared_ptr을 참조하는 std::weak_ptr (C++ 11은 다시 C++ 03의 경우 std::tr1::weak_ptr을 사용)을 만들 수 있습니다. shared_ptr이 실제로 해당 객체를 삭제하면 weak_ptr 모두이를 파악할 수 있습니다.

Npc 님이 아직 다른 곳에서 사용되고있는 이유는 무엇입니까? (예 : 여전히 조치가있는 것). 이러한 다른 참조가 모두 Npc을 삭제했음을 발견하는 대신, 모든 참조가 사라지면 Npc을 죽이면됩니다. shared_ptr 만 사용하면 (weak_ptr) 제대로 작동합니다.

+0

게임 메커니즘이 작동하는 방식이기 때문에 제가 설명한 접근법을 사용하고 싶습니다. NPC는 언제든지 죽을 수 있으며 더 이상 행동을 취하거나 맵의 일부가 될 수 없다는 것을 완벽하게 이해합니다. NPC가 사망 한 후에도 의미있는 코드가 실행되는 것을 원하지 않으며 사망 한 직후에 해당 객체를 삭제하는 한 가지 방법이 필요합니다. – Saage

+0

@Saage : NPC가 죽으면 NPC가 삭제되기 전에 사전에 애니메이션을 제거하고 맵에서 해당 존재를 제거 할 것입니다 (또는 나쁜 생각일지도 모르는). 나중에 NPC가 사라 졌다는 사실을 깨닫기 위해지도와 행동 목록에 의존합니다. 이렇게하면 크기에 대한 작업 목록을 쿼리하고 실제로 보류중인 작업 수를 확인하는 등의 작업을 수행 할 수 있습니다. –

3

제공하신 정보를 통해 Observer Pattern을 구현하는 것이 좋습니다. NPC의 죽음에 대응해야하는 코드가있는 경우이 패턴을 사용하는 것이 좋습니다. NPC에 대한 포인터 참조가있는 코드 섹션은 NPC 사망시 알림을받으며 NPC에 대한 포인터 복사본을 무시하고 필요한 경우 NPC의 죽음에 대응합니다. 사망 통지는 NPC가 실제로 삭제되기 전에 모든 observers에게 전송됩니다.

이 패턴을 사용하면 "살인 한 몬스터마다 영웅이 50 HP가 증가합니다."와 같은 메 커닉을 구현할 수 있으며 쉽게 확장 할 수 있습니다.

NPC의 죽음에 적극적으로 대응해야하는 코드가없고 NPC가 죽은 경우에만 처리해야하는 경우 Kevin Ballard의 제안 인 shared_ptr을 사용할 수도 있습니다.

+0

간단하게 들리므로'shared_ptr'을 사용하게 될 것 같지만, Observer 패턴은 훌륭한 아이디어이며, 나는 그것을 유용하게 사용합니다. 감사합니다! – Saage

0

하나의 옵션은 수업에 참조 횟수를 포함시키는 것입니다. 어떤 다른 객체 (예 : 방)가 npc에 대한 포인터를 보유 할 때, 방은 npc의 참조 카운트를 증가시킬 책임이 있습니다. 이제는 죽은 npc를 삭제하는 대신, 죽은 것으로 플래그를 지정합니다 (아직 올바른 플래그가없는 경우 다른 새 데이터 멤버를 통해). 참조 카운트가 0이면 삭제합니다. room 객체는 또한 그 플래그를 주기적으로 검사 할 책임이 있으며 npc가 죽었다는 것을 알게되면 참조 카운트를 감소시킵니다 (카운트가 0이되면 사후 삭제가 발생합니다).