Einfacher, effizienter Schwachzeiger, der auf NULL gesetzt wird, wenn der Zielspeicher freigegeben wird

8

Gibt es einen einfachen, effizienten schwachen / geschützten Zeiger? Ich brauche mehrere Zeiger auf dasselbe Objekt, die alle automatisch auf NULL gesetzt werden, wenn das Objekt gelöscht wird. Es gibt einen "Master" -Zeiger, der immer zum Löschen des Objekts verwendet wird, aber es können mehrere andere Zeiger sein, die auf dasselbe Objekt verweisen.

Hier sind einige Lösungen, die nicht ganz meinen Anforderungen entsprechen:

  • QPointer : Ich entwickle keine QT-App; Ich möchte diese Bibliothek nicht aufnehmen / von QObject ableiten.
  • boost :: weak_ptr : Beim Zugriff auf eine aufgehobene Zuordnung wird eine Ausnahme ausgelöst Objekt. Zu teuer für meine Situation: Es sollte normal sein, einen schwachen Zeiger zu testen; Ich plane eine manuelle Bereinigung, wenn ein schwacher Zeiger nicht mehr gültig ist. update : weak_ptr kann getestet werden, ohne Ausnahmen auszulösen
  • Low-Overhead Weak Pointer : Das ist sehr nah an dem, was ich suche für, außer ich mag die Tatsache nicht "Dieses Schema funktioniert nur garantiert, solange Sie nicht 2 ** sizeof (int) -Zeiten am selben Ort zuweisen."

Warum brauche ich diese schwachen / geschützten Zeiger: Ich habe ein Spiel mit einer Liste von Spielobjekten. Einige Objekte sind abhängig von anderen, beispielsweise einem debug / stats-Objekt, das einer Spieleinheit zugeordnet ist. Das Debug / Status-Objekt zeigt nützliche Informationen über die Spieleinheit an, aber es macht nur Sinn, solange die Spieleinheit existiert. Wenn also die Spieleinheit gelöscht wird, sollte das Objekt debug / stats dies erkennen und sich selbst löschen. (Eine andere Idee ist ein Tracking Rakete: anstatt sich selbst zu löschen, kann es nach einem neuen Ziel suchen.)

Ich möchte die debug / stats-Logik von der Spieleinheit getrennt halten. Die Spieleinheit sollte nicht wissen müssen, dass ein debug / stats-Objekt an sie angehängt ist. Während ich eine Antwort für schwache / bewachte Zeiger bevorzuge, begrüße ich auch verschiedene Möglichkeiten, meine spezifische Aufgabe anzugehen. Ich denke, dass ich einen Spielobjektmanager implementieren muss, der die Objektlebensdauer verfolgt und verwendet Handles anstelle von rohen Zeigern zu Speicheradressen.

Ich entwickle in C ++.

    
Leftium 09.12.2009, 19:15
quelle

2 Antworten

16

Sie können das lock() -Member von boost::weak_ptr verwenden, um den Wert von weak_ptr testen und dann verwenden zu können, ohne dass Ausnahmen berücksichtigt werden müssen.

    
Michael Burr 09.12.2009, 19:19
quelle
10

Dies ist eine häufige Sache in der Spieleentwicklung. In der Regel wird ein System von Objekt-Handles verwendet, anstatt schwache Zeiger zu boosten, da wir die zugrundeliegende Nachschlagetabelle als konstanten Speicher benötigen und manchmal brauchen wir zusätzliche Informationen oder Garantien, die Boost nicht bekommen hat.

Der übliche Ansatz besteht darin, eine Ausarbeitung von Zeigern auf Zeiger zu verwenden. Auf eine Entität wird mit Handle und nicht mit Zeiger verwiesen. Das Handle ist ein Index in ein großes Array von Zeigern auf Entitäten. Wenn eine Entität stirbt, NULLt sie den Zeiger in ihrer Entitätstabelle aus.

%Vor%

Die Seriennummer ist notwendig, weil das Array eine konstante Größe hat - schließlich müssen Sie Entitätstabelleneinträge recyceln, und es besteht die Möglichkeit, dass Sie ein Handle z. B. für Index # 743 speichern, das lange genug ist Objekt wird gelöscht und Zelle # 743 für etwas anderes wiederverwendet. Wenn Sie einfach einen Zeiger auf eine Liste von Zeigern hätten, hätten Sie am Ende ein Handle, das auf ein ganz anderes Objekt zeigt, statt NULL zu sein. Also geben wir jeder Entität eine global eindeutige Nummer und speichern diese auch im Handle.

Sie könnten natürlich einen Standardvektor oder eine Map oder ein Dictionary oder eine andere Art von Datenstruktur für die Entitätentabelle verwenden, aber unsere Anforderungen waren typischerweise für konstanten Speicher, Cache-Kohärenz und absolute maximale Leistung (seit handle_t :: Get () wird tausende Male pro Frame aufgerufen).

    
Crashworks 09.12.2009 20:10
quelle

Tags und Links