Wie erstellt man ein c ++ 11 std :: unordered_set von std :: weak_ptr

8

Ich habe ein Set wie folgt: set<weak_ptr<Node>, owner_less<weak_ptr<Node> > > setName;

Es funktioniert gut. Aber ich würde es gerne in ein ungeordnetes Set umwandeln. Allerdings bekomme ich ungefähr sechs Seiten Fehler, wenn ich das tue. Irgendwelche Ideen, wie man das macht?

Nachdem ich alle Seiten von Fehlermeldungen durchsucht habe, habe ich Zeilen gefunden, die helfen könnten.

%Vor%     
user1404617 04.12.2012, 03:30
quelle

4 Antworten

3

Da unordered_sets Hash-basiert sind, müssen Sie ein Hash Funktionsobjekt angeben der Datentyp std :: weak_ptr.

Wenn Sie sich die unordered_set Template-Parameter ansehen

%Vor%

Sie werden bemerken, dass std :: unordered_set Ihnen einen Standard std :: hash & lt; & gt; Vorlagenparameter. Aber da std :: hash nur Spezialisierungen für einen spezifischen Satz von Datentypen bietet, könnten Sie das tun muss dir deine eigenen zur Verfügung stellen.

Die von Ihnen angegebene Fehlermeldung sagt Ihnen, dass kein std :: hash & lt; & gt; Spezialisierung für std :: weak_ptr & lt; & gt; existiert, also müssen Sie dafür Ihre eigene Hashfunktion bereitstellen:

%Vor%

Bearbeiten: Sie müssen auch eine Gleichheitsfunktion bereitstellen, da kein std :: equal_to für weak_ptr angegeben wird. Einen möglichen Weg dazu aus "Gleichheitsvergleich std :: weak_ptr" auf Stackoverflow nehmen:

%Vor%

Alles zusammen ergibt folgendes:

%Vor%     
lx. 04.12.2012, 15:30
quelle
9

Ich denke nicht, dass die vorgeschlagene Hash-Funktion korrekt ist. Wenn alle geteilten Zeiger auf das Objekt verschwinden, gibt weak_ptr<X>::lock() leer shared_ptr zurück, dessen Hashwert wahrscheinlich Null ist. So kann die Hash-Funktion im Laufe der Zeit verschiedene Werte zurückgeben.

Ich denke, dass die richtige Lösung hier zu verwenden ist %Code%. Der Typ boost::unordered_map<X*, boost::weak_ptr<X>> kann leicht als Schlüssel für die Hash-Zuordnung und X* verwendet werden, da der Wert die Möglichkeit bietet, herauszufinden, ob das referenzierte Objekt noch existiert.

Um den Wert für diesen Hashwert zu speichern, können Sie Folgendes verwenden:

%Vor%     
faramir 01.03.2014 05:48
quelle
8

Die kurze und unglückliche Antwort ist, dass shared_ptr<> zwar sicher als Schlüssel in einem ungeordneten Satz oder einer Karte verwendet werden kann und nicht kann. Keine Menge Tricks kann es sicher machen.

Dies liegt daran, dass die Schnittstelle von weak_ptr<> den Zugriff auf das gemeinsam genutzte Steuerelementobjekt nicht freigibt. Dies ist die Grundlage für den Vergleich von weak_ptr , wenn es in einer geordneten Menge oder Karte verwendet wird.

Obwohl es sinnvoll erscheint, den Zeiger zu sperren und dann den owner_before() zu hacken, ist dies nicht der Fall. Wenn der letzte shared_ptr den Gültigkeitsbereich verlässt, ändert sich der Hashwert, was beim nächsten Iterieren des Sets oder der Map zu einem undefinierten Verhalten führt. Dies wird höchstwahrscheinlich unbemerkt bleiben, bis Ihr Code vor Kunden produziert wird, bei denen gelegentlich unerwarteter und unerklärlicher Funktionsverlust auftritt. Ihre Komponententests werden jedoch weiterhin fehlerfrei verlaufen, was Ihnen die falsche Vorstellung vermittelt, dass Ihre Testabdeckung gut ist. Ihr Code ist zuverlässig und es sind die Benutzer, die Hardware oder das Netzwerk, die dafür verantwortlich sind.

Zusammenfassend gesagt, wenn Sie shared_ptr rs verwenden, um Ihre nicht-eigenen Objekt-Caches zu erstellen (für die sie ausgezeichnet sind), müssen Sie weak_pt verwenden und den winzigen Performance-Treffer erleiden (obwohl Realität wird dies durch den Leistungsverlust, der durch die std::set<weak_ptr> verursacht wird, die das Set schützt, in den Schatten gestellt.

Wenn Sie wirklich mutex als ungeordneten Schlüssel verwenden möchten, müssen Sie einen eigenen schreiben (Hinweis: Verwenden Sie die Adresse des gemeinsamen Steuerblocks als Basis für die Hash-Funktion).

    
Richard Hodges 18.06.2015 17:49
quelle
-1

Dank lx wird jetzt folgender Code erstellt. Um es mit gcc 4.7.2 zu erstellen, musste ich zwei weitere 'const' hinzufügen, also sollte der folgende Code ein vollständiges Arbeitsbeispiel sein, um std :: weak_ptr in ein std :: unordered_set zu setzen.

%Vor%     
user1404617 07.12.2012 03:37
quelle