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?
An explicit delete for a unique_ptr would be reset() . But do remember that unique_ptr are there so that you don't have to manage directly the memory they hold. That is, you should know that a unique_ptr will safely delete its underlying raw pointer once it goes out of scope.
vector::erase() erase() function is used to remove elements from a container from the specified position or range.
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();
}
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();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With