简体   繁体   English

从带有原始指针的向量中删除std :: unique_ptr的最佳方法是什么?

[英]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 : 然后我有另一个包含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 . 如果里面有一个元素myOtherVector这也将是内部myVector ,所以我想通过在每个元素myOtherVector和删除相同的元素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. 这会产生编译时错误,因为myVector包含唯一指针,但我给remove()函数一个原始指针。 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. 所有这一切都是不正确的,因为现在我有两个std::unique_ptr引用同一个对象。 The element inside myVector contains a reference and the construction of the unique pointer in the above line is another reference. myVector中的元素包含一个引用,上面一行中唯一指针的构造是另一个引用。 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." 当我运行应用程序时, myVector.erase()行导致运行时错误,表示“ApplicationName.exe已触发断点”。 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. std::unique_ptr有一个成员函数get ,它返回拥有的指针。

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); 它使用remove_if有选择地从第一个容器( myVector )中删除所有指向第二个容器(myOtherVector)元素指向的对象的元素; then, it clears the second container. 然后,它清除第二个容器。 The predicate is implemented through a lambda function: 谓词是通过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();
}

If you cant simplify your problem, how about std::set_difference or one of its kin ( http://www.cplusplus.com/reference/algorithm/set_difference/ )? 如果你不能简化你的问题,std :: set_difference或其中一个家伙( 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 您需要指定一个比较函数来get()来自unique_ptr的原始指针

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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