Le meilleur moyen de supprimer un std :: unique_ptr d’un vecteur avec un pointeur brut?

J’ai donc un vecteur comme celui-ci:

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

Ensuite, j’ai un autre vecteur qui contient des pointeurs bruts de SomeClass :

 std::vector myOtherVector; 

S’il existe un élément dans myOtherVector il le sera également dans myVector . Je souhaite donc parcourir chaque élément de myOtherVector et supprimer le même élément de myVector . Ensuite, effacez le vecteur. Voici ce que je suis venu avec:

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

Cela produit une erreur de compilation car myVector contient des pointeurs uniques, mais je donne à la fonction remove() un pointeur brut. C’est là que j’ai besoin d’aide, car je ne sais pas comment résoudre ce problème. J’ai changé la ligne en:

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

Tout d’abord, c’est incorrect, car j’ai maintenant deux std::unique_ptr référençant le même object. L’élément dans myVector contient une référence et la construction du pointeur unique dans la ligne ci-dessus est une autre référence. Et je ne sais même pas si construire un nouveau pointeur pour obtenir le même type est la bonne façon de procéder. Alors, j’ai changé les pointeurs uniques en points partagés:

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

Lorsque j’ai exécuté l’application, la ligne myVector.erase() a généré une erreur d’exécution myVector.erase() que “ApplicationName.exe a déclenché un point d’arrêt”. En cliquant sur Continuer, j’ai eu un échec d’assertion de débogage.

Alors évidemment, je fais quelque chose de mal, mais je ne sais pas quoi. Quelle est la bonne façon d’effacer un pointeur intelligent d’un vecteur avec un pointeur brut?

Voici comment je le ferais. Les performances pourraient être améliorées, mais tant que cela ne s’avérera pas un goulot d’étranglement pour votre application, cela ne me dérangerait pas. L’algorithme est simple et clair.

Il utilise remove_if pour supprimer sélectivement du premier conteneur ( myVector ) tous les éléments pointant vers des objects pointés par des éléments du second conteneur (myOtherVector); ensuite, il efface le deuxième conteneur. Le prédicat est implémenté via une fonction lambda:

 #include  #include  #include  struct SomeClass { /* ... */ }; int main() { std::vector> myVector; std::vector myOtherVector; myVector.erase( std::remove_if( // Selectively remove elements in the second vector... myVector.begin(), myVector.end(), [&] (std::unique_ptr 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(); } 

std::unique_ptr a une fonction membre, get , qui retourne le pointeur appartenant.

Considérer ce qui suit:

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

Si vous ne pouvez pas simplifier votre problème, que diriez-vous de std :: set_difference ou de l’un de ses parents ( http://www.cplusplus.com/reference/algorithm/set_difference/ )?

Vous devez spécifier une fonction de comparaison pour obtenir le pointeur brut de unique_ptr.