简体   繁体   中英

Best way to delete a std::unique_ptr from a vector with a raw pointer?

So I have a vector like so:

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

Then I have another vector which contains raw pointers of SomeClass :

std::vector<SomeClass*> myOtherVector;

If there is an element inside myOtherVector it will also be inside myVector , so I want to go through each element in myOtherVector and remove the same element from myVector . Then clear out the vector. This is what I came up with:

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

This produces a compile time error because myVector holds unique pointers but I'm giving the remove() function a raw pointer. This is where I need help because I don't know what the proper way to solve this problem would be. I changed the line to:

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

Frist of all this is incorrect because now I have two std::unique_ptr s referencing the same object. The element inside myVector contains a reference and the construction of the unique pointer in the above line is another reference. And I don't even know if constructing a new pointer to get the same type is conceptually the correct way to go about doing this. So then I changed the unique pointers to shared pointers:

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

When I ran the application the myVector.erase() line resulted in a runtime error which said "ApplicationName.exe has triggered a breakpoint." upon clicking continue I got a debug assertion failure.

So obviously I'm doing something wrong, but I don't know what. What is the correct way to erase a smart pointer from a vector with a raw pointer?

std::unique_ptr has a member function, get , that returns the owned pointer.

Consider the following:

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

This is how I would do it. Performance could be improved, but as long as it won't prove to be a bottleneck for your application, I would not bother with that. The algorithm is simple and clear.

It uses remove_if to selectively remove from the first container ( myVector ) all the elements pointing to objects that are pointed to by elements of the second container (myOtherVector); then, it clears the second container. The predicate is implemented through a lambda function:

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

If you cant simplify your problem, how about std::set_difference or one of its kin ( http://www.cplusplus.com/reference/algorithm/set_difference/ )?

You would need to specify a compare function to get() the raw pointer from the unique_ptr

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM