2013-02-28 7 views
5

So habe ich ein Vektor wie so:Der beste Weg, um ein std :: unique_ptr aus einem Vektor mit einem rohen Zeiger zu löschen?

std::vector<std::unique_ptr<SomeClass>> myVector; 

Dann habe ich einen anderen Vektor, der rohe Zeiger von SomeClass enthält:

std::vector<SomeClass*> myOtherVector; 

Wenn es ein Element innerhalb myOtherVector ist es auch innerhalb myVector sein wird, Ich möchte also jedes Element in myOtherVector durchlaufen und das gleiche Element aus myVector entfernen. Dann lösche den Vektor. Das ist, was ich kam mit:

for(size_t i = 0; i < myOtherVector.size(); i++) 
{ 
    myVector.erase(std::remove(myVector.begin(), myVector.end(), myOtherVector[i]), myVector.end()); 
} 
myOtherVector.clear(); 

Dies erzeugt einen Kompilierung-Fehler, weil myVector eindeutige Zeiger hält, aber ich bin der remove() Funktion einen Rohzeiger geben. Hier brauche ich Hilfe, weil ich nicht weiß, wie der richtige Weg zur Lösung dieses Problems aussehen könnte. Ich habe die Zeile:

myVector.erase(std::remove(myVector.begin(), myVector.end(), std::unique_ptr<SomeClass>(myOtherVector[i])), myVector.end()); 

Frist all dies falsch ist, denn jetzt habe ich zwei std::unique_ptr s das gleiche Objekt verweisen. Das Element innerhalb myVector enthält eine Referenz und die Konstruktion des eindeutigen Zeigers in der obigen Zeile ist eine weitere Referenz. Und ich weiß nicht einmal, ob das Konstruieren eines neuen Zeigers, um denselben Typ zu erhalten, konzeptionell der richtige Weg ist, dies zu tun. Also änderte ich die einzigartigen Zeiger auf gemeinsame Zeiger: „ApplicationName.exe einen Breakpoint ausgelöst hat“

std::vector<std::shared_ptr<SomeClass>> myVector; 
std::vector<SomeClass*> myOtherVector; 

for(size_t i = 0; i < myOtherVector.size(); i++) 
{ 
    myVector.erase(std::remove(myVector.begin(), myVector.end(), std::shared_ptr<SomeClass>(myOtherVector[i])), myVector.end()); 
} 
myOtherVector.clear(); 

Wenn ich die Anwendung lief die myVector.erase() Linie in einem Laufzeitfehler geführt, die die Beim Klicken auf "Fortfahren" kam es zu einem Debug-Assertion-Fehler.

Also offensichtlich mache ich etwas falsch, aber ich weiß nicht was. Was ist der richtige Weg, um einen intelligenten Zeiger von einem Vektor mit einem rohen Zeiger zu löschen?

+0

Sie die Probleme durch Vereinfachung betrachtet haben nicht nur einen Vektor von rohen Zeiger beibehalten zu beginnen? –

+0

'std :: unique_ptr' hat ein 'get'-Element, das den eigenen Zeiger zurückgibt. –

+1

Uh, ein Vorschlag. Es gibt einen weiteren intelligenten C++ 11-Zeiger namens 'std :: shared_ptr'. –

Antwort

1

Dies ist, wie ich es tun würde. Die Leistung könnte verbessert werden, aber solange es sich nicht als Engpass für Ihre Anwendung erweist, würde ich mich nicht darum kümmern. Der Algorithmus ist einfach und klar.

Es verwendet remove_if, um selektiv aus dem ersten Container (myVector) alle Elemente zu entfernen, die auf Objekte zeigen, auf die von Elementen des zweiten Containers (myOtherVector) verwiesen wird; dann löscht es den zweiten Behälter. Das Prädikat wird durch eine Lambda-Funktion implementiert:

#include <vector> 
#include <memory> 
#include <algorithm> 

struct SomeClass { /* ... */ }; 

int main() 
{ 
    std::vector<std::unique_ptr<SomeClass>> myVector; 
    std::vector<SomeClass*> myOtherVector; 

    myVector.erase(
     std::remove_if(// Selectively remove elements in the second vector... 
      myVector.begin(), 
      myVector.end(), 
      [&] (std::unique_ptr<SomeClass> const& p) 
      { // This predicate checks whether the element is contained 
       // in the second vector of pointers to be removed... 
       return std::find(
        myOtherVector.cbegin(), 
        myOtherVector.cend(), 
        p.get() 
        ) != myOtherVector.end(); 
      }), 
     myVector.end() 
     ); 

    myOtherVector.clear(); 
} 
3

std::unique_ptr hat eine Elementfunktion, get, die den eigenen Zeiger zurückgibt.

Beachten Sie Folgendes:

std::sort(myOtherVector.begin(), myOtherVector.end()); 

myVector.erase(std::remove_if(myVector.begin(), myVector.end(), 
[&](std::unique_ptr<SomeClass> const& p) -> bool 
{ 
    return std::binary_search(myOtherVector.begin(), myOtherVector.end(), 
           p.get()); 
})); 

myOtherVector.clear();