繁体   English   中英

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

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

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

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已触发断点”。 点击继续,我得到一个调试断言失败。

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

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

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

它使用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();
}

如果你不能简化你的问题,std :: set_difference或其中一个家伙( http://www.cplusplus.com/reference/algorithm/set_difference/ )怎么样?

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

暂无
暂无

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

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