in set mit smart-Pointer nach Zeiger suchen
-
hab ein set:
std::set< boost::shared_ptr< SomeClass > > ints;
Und hab nen Zeiger auf eine Instanz von SomeClass, die in dem set drin ist. Leider aber nur nen Zeiger, nicht keinen shared_ptr.
Wie kann ich das finden (ohne linear zu suchen)?
-
Wie kann ich das finden (ohne linear zu suchen)?
Ich würde mal sagen über die set gar nicht. Denn selbst wenn du den Raw-Pointer temporär in einen shared_ptr umwandeln könntest, würdest du den Wert nicht finden, denn: "two shared_ptr instances are equivalent if and only if they share ownership"
Ich sehe folgende Möglichkeiten:
1. du verwendest std::equal_range mit einem passenden cmp-Objekt:struct Cmp { public: bool operator()(const boost::shared_ptr<SomeClass>& lhs, SomeClass* rhs) const { return lhs.get() == rhs; } bool operator()(SomeClass* lhs, const boost::shared_ptr<SomeClass>& rhs) const { return lhs == rhs.get(); } }; typedef std::set< boost::shared_ptr< SomeClass > > Set; void func(SomeClass* p, Set& s) { std::pair<Set::iterator, Set::iterator> res = std::equal_range(s.begin(), s.end(), p, Cmp()); if (res.first != res.second) // gefunden }
Das ist zumindest in der Anzahl der Vergleiche logarithmisch. Da sets Iteratoren aber keine Random-Access-Iteratoren sind ist die Anzahl der nötigen Schritte natürlich linear in end()-begin().
2. Du änderst die set in eine map.
3. Du änderst dein Design so, dass du niemals gleichzeitig die selbe Ressource sowohl über einen Shared-Ptr als auch über einen Raw-Pointer referenzierst. Das ist generell eine gute Idee, da die Mischung von Raw- und Shared-Ptr irgendwie immer zu Problemen führt.
Kannst du z.B. nicht statt der Raw-Pointer Iteratoren verwenden?Drittens ist natürlich am Schönsten, aber sicher nicht in allen Situationen möglich.
-
doppelposting
-
Mein Fall ist eigentlich ein Anwendungsfall für boost::weak_ptr. Das Objekt aus dem Container zu holen, wär eh schon ne schmutzige Lösung (wär aber schnell zu implementieren gewesen. Bin nämlich ziehmlich unter Druck, wegen des Problems: Hab ein Speicherleck wegen zwei Smart-Pointer-Objekten, die sich gegenseitig referenzieren.
Blos hab ich leider in meinem realen Fall keine boost sondern einen selber geschriebenen referenzzählenden Smart-Pointer. Den verwend ich zwar eigentlich nicht mehr, aber der Code ist ein bisschen älter. Umstellen wäre auch ein ziehmlicher Aufwand.
Hab inzwischen Angefangen, mir selber ne weak_ptr-Pendant zu schreiben. Is ja eigentlich garnet so schwierig:
Könnt mal angucken, ob ich was wichtiges vergessen hab
namespace tz { template <class T> class CXtAutoP { friend class CXtAutoPRef<T>; //... //privater Ctor CXtAutoP( T* Pointer, unsigned* puInstanzenZaehler) :m_Pointer( Pointer), m_puInstanzenZaehler( puInstanzenZaehler) { ++*puInstanzenZaehler; //Übernimmt Besitz -> hochzählen! }; //... }; } namespace tz { /// Nicht-Besitzende Referenz auf ein mit einem CXtAutoP gemanagetes Objekt /// (erfüllt dieselbe Aufgabe wie boost::weak_ptr) template <typename T> class CXtAutoPRef { ///Zeiger auf Objekt T* m_Pointer; //Zeiger auf Zähler unsigned* m_puInstanzenZaehler; public: CXtAutoPRef( const etz::CXtAutoP< T>& xap) :m_Pointer( xap.m_Pointer), m_puInstanzenZaehler( xap.m_puInstanzenZaehler) { } const etz::CXtAutoP< T> GetXap() { return etz::CXtAutoP<T>( m_Pointer, m_puInstanzenZaehler); } }; }