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

时间:2013-02-28 01:04:53

标签: c++ std smart-pointers stdvector

所以我有一个这样的矢量:

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

然后我有另一个包含SomeClass的原始指针的向量:

std::vector<SomeClass*> myOtherVector;

如果myOtherVector中有元素,它也会在myVector内,所以我想浏览myOtherVector中的每个元素并从myVector中删除相同的元素。然后清除矢量。这就是我想出的:

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

这会产生编译时错误,因为myVector包含唯一指针,但我给remove()函数一个原始指针。这是我需要帮助的地方,因为我不知道解决这个问题的正确方法是什么。我将行改为:

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

所有这一切都是错误的,因为现在我有两个std::unique_ptr引用相同的对象。 myVector内的元素包含一个引用,上面一行中唯一指针的构造是另一个引用。我甚至不知道构造一个新的指针来获得相同类型在概念上是否正确的方法去做这件事。然后我将唯一指针更改为共享指针:

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

当我运行应用程序时,myVector.erase()行导致运行时错误,表示“ApplicationName.exe已触发断点”。点击继续,我得到一个调试断言失败。

显然我做错了什么,但我不知道是什么。使用原始指针从向量中擦除智能指针的正确方法是什么?

3 个答案:

答案 0 :(得分:3)

std::unique_ptr有一个成员函数get,它返回拥有的指针。

请考虑以下事项:

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

答案 1 :(得分:2)

我就是这样做的。性能可以提高,但只要它不会被证明是您的应用程序的瓶颈,我不会打扰它。算法简单明了。

它使用remove_if有选择地从第一个容器(myVector)中删除所有指向第二个容器(myOtherVector)元素指向的对象的元素;然后,它清除第二个容器。谓词是通过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();
}

答案 2 :(得分:0)

如果你无法简化你的问题,那么std :: set_difference或其中一个亲属(http://www.cplusplus.com/reference/algorithm/set_difference/)怎么样?

您需要指定一个比较函数来get()来自unique_ptr

的原始指针