2009-12-09 8 views
8

Czy istnieje prosty, skuteczny wskaźnik słabo/bezpiecznie? Potrzebuję wielu wskaźników do tego samego obiektu, które są automatycznie ustawiane na wartość NULL po usunięciu obiektu. Istnieje jeden "główny" wskaźnik, który jest zawsze używany do usuwania obiektu, ale może istnieć kilka innych wskaźników, które odwołują się do tego samego obiektu.Prosty, skuteczny słaby wskaźnik ustawiony na wartość NULL po zwolnieniu pamięci docelowej

Oto kilka rozwiązań, które nie bardzo pasują do moich potrzeb:

  • QPointer: Nie będę się tworzeniem aplikacji Qt; Nie chcę włączać tej biblioteki/pochodnej z QObject.
  • boost::weak_ptr: Wyjątek jest zgłaszany podczas uzyskiwania dostępu do obiektu przydzielonego. Zbyt droga w mojej sytuacji: test słabej wskazówki powinien być normalny; Planuję wykonać ręczne czyszczenie, gdy słaby wskaźnik przestanie być poprawny.aktualizacja: weak_ptr można testować bez rzucania wyjątków
  • Low-Overhead Weak Pointers: To jest bardzo blisko tego, co szukam, z wyjątkiem I nie podoba się fakt „Ten schemat jest gwarantowana jedynie pracować tak długo, jak don” t przydzielić 2 ** sizeof (int) razy w tej samej lokalizacji. "

Dlaczego muszę te słabe/strzeżone wskazówek: mam grę z listy obiektów do gier. Niektóre obiekty są zależne od innych, na przykład obiekt debugowania/statystyki powiązany z obiektem gry. Obiekt debugowania/stanu wyświetla przydatne informacje o obiekcie gry, ale ma sens tylko wtedy, gdy istnieje gra. Jeśli obiekt gry zostanie usunięty, obiekt debug/stats powinien to zrobić i usunąć sam siebie. (Innym pomysłem jest pocisk śledzący: zamiast usuwać się, może szukać nowego celu.)

Chcę zachować logikę debugowania/statystyk oddzielnie od encji gry. Obiekt gry nie powinien wiedzieć, że do obiektu dołączony jest obiekt debug/stats. Chociaż wolę odpowiedź dla słabych/strzeżonych wskaźników, z zadowoleniem przyjmuję także różne sposoby podejścia do mojego konkretnego zadania. Myślę, że być może będę musiał zaimplementować game object manager, który śledzi życiowe obiekty i używa uchwytów zamiast surowych wskaźników do adresów pamięci.

Pracuję w C++.

+0

Ogólne pytanie brzmi: "czy Qt jest właściwym wyborem do stworzenia gry?" –

+3

Słaby wskaźnik Boost pozwala sprawdzić, czy jest on ważny. Zgłasza wyjątek tylko wtedy, gdy próbujesz go bezpośrednio usunąć - podobnie do tego, co się dzieje, gdy próbujesz wyłuskać wskaźnik zerowy. – jalf

+0

C++ 11 ma ['std :: weak_ptr'] (http://en.cppreference.com/w/cpp/memory/weak_ptr). Wygląda podobnie do tego z Boost. – Palec

Odpowiedz

16

Możesz użyć elementu lock() z boost::weak_ptr, aby móc przetestować (następnie użyć) wartość weak_ptr bez rozwiązywania wyjątków.

10

Jest to typowe zjawisko w tworzeniu gier. Zazwyczaj używany jest raczej system uchwytów obiektów niż Wzmocnienie słabych wskaźników, ponieważ potrzebujemy podstawowej tabeli odnośników do stałej pamięci i ponieważ czasami potrzebujemy dodatkowych informacji lub gwarancji, że Boost nie ma.

Zazwyczaj stosuje się opracowanie na wskaźnikach do wskaźników. Obiekt odwoływany jest przez uchwyt, a nie przez wskaźnik. Klamka jest indeksem do dużej grupy wskaźników do podmiotów. Kiedy jednostka umiera, NULLuje wskaźnik w swojej tablicy encji.

struct handle_t 
{ 
    uint32 serialnumber; // this is a GUID for each entity; it increases 
         // monotonically over the life of the process 
    uint entityindex; 
    inline Entity *Get(); 
} 

struct entityinfo_t 
{ 
    Entity *pEntity; // an entity's destructor NULLs this out on deletion 
    uint32 serialnumber; 
} 

entityinfo_t g_EntityTable[MAX_ENTITIES]; 

Entity *handle_t::Get() 
{ 
    entityinfo_t &info = g_EntityTable[entityIndex]; 
    if (serialnumber == info.serialnumber) 
    { 
    return info.pEntity; 
    } 
    else 
    { 
     return NULL; 
    } 
} 

Numer seryjny jest konieczne, ponieważ tablica jest od stałej wielkości - w końcu trzeba będzie recykling elementów tabeli jednostka, i istnieje możliwość, że może przechowywać uchwyt do, powiedzmy, Wskaźnik 743, wystarczająco długo, aby obiekt został usunięty, a komórka # 743 ponownie użyta do czegoś innego.Gdybyś po prostu miał wskaźnik do listy wskaźników, skończyłby się uchwytem, ​​który wskazywałby na zupełnie inny obiekt, niż na NULL. Dlatego nadajemy każdej jednostce globalnie unikalny numer i przechowujemy ją również w uchwycie.

Oczywiście można użyć wektorowego wzorca lub mapy, słownika lub jakiejś innej struktury danych, ale nasze wymagania dotyczą zwykle stałej pamięci, spójności pamięci podręcznej i absolutnej maksymalnej wydajności (ponieważ handle_t :: Get() otrzymuje tysiące razy na klatkę).

Powiązane problemy