2013-02-28 10 views
5

Così ho un vettore in questo modo:Il modo migliore per cancellare uno std :: unique_ptr da un vettore con un puntatore raw?

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

Poi ho un altro vettore che contiene i puntatori prime di SomeClass:

std::vector<SomeClass*> myOtherVector; 

Se c'è un elemento all'interno myOtherVector sarà anche all'interno myVector, quindi voglio passare attraverso ogni elemento in myOtherVector e rimuovere lo stesso elemento da myVector. Quindi cancella il vettore. Questo è ciò che mi si avvicinò con:

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

Questo produce un errore di compilazione perché myVector contiene dei puntatori unici ma io sto dando la funzione remove() un puntatore crudo. Qui è dove ho bisogno di aiuto perché non so quale sia il modo corretto per risolvere questo problema. Ho cambiato la linea a:

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

Frist di tutto questo non è corretto perché ora ho due std::unique_ptr s fanno riferimento allo stesso oggetto. L'elemento all'interno di myVector contiene un riferimento e la costruzione del puntatore univoco nella riga sopra è un altro riferimento. E non so nemmeno se costruire un nuovo puntatore per ottenere lo stesso tipo sia concettualmente il modo corretto per farlo. Così poi ho cambiato i puntatori uniche per puntatori condivisi: "NomeApplicazione.exe ha innescato un punto di interruzione"

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(); 

Quando ho eseguito l'applicazione della linea myVector.erase() ha provocato un errore di runtime, che ha detto dopo aver fatto clic su Continua ho ottenuto un errore di asserzione di debug.

Quindi ovviamente sto facendo qualcosa di sbagliato, ma non so cosa. Qual è il modo corretto di cancellare un puntatore intelligente da un vettore con un puntatore raw?

+0

Avete considerato semplificare il problema, che da solo non mantenere un vettore di puntatori prime per cominciare? –

+0

'std :: unique_ptr' ha un membro' get' che restituisce il puntatore di proprietà. –

+1

Uh, un suggerimento. C'è un altro puntatore intelligente C++ 11 chiamato 'std :: shared_ptr'. –

risposta

1

Questo è come io lo farei. Le prestazioni potrebbero essere migliorate, ma finché non si rivelerà un collo di bottiglia per la tua applicazione, non mi preoccuperei di questo. L'algoritmo è semplice e chiaro.

Utilizza remove_if per rimuovere selettivamente dal primo contenitore (myVector) tutti gli elementi che puntano agli oggetti puntati da elementi del secondo contenitore (myOtherVector); quindi, cancella il secondo contenitore. Il predicato è attuato mediante una funzione lambda:

#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 ha una funzione membro, get, che restituisce il puntatore di proprietà.

Si consideri il seguente:

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();