std :: vector中的c-std :: remove_if polymorphic std :: unique_ptr

前端之家收集整理的这篇文章主要介绍了std :: vector中的c-std :: remove_if polymorphic std :: unique_ptr前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个三级的等级,派生从可选和可绘制派生.然后我有一个向量的unique_ptr< Drawable>我用Derived对象填充.

我确定向量只能由同时来自两个基地的对象填充.

当我尝试通过使用指向Selected的指针从矢量中删除某个元素时,问题出现.

#include <vector>
#include <memory>
#include <algorithm>

struct Selectable {
    virtual ~Selectable() = 0;
};
Selectable::~Selectable() = default;

struct Drawable {
    virtual ~Drawable() = 0;
};
Drawable::~Drawable() = default;

struct Derived : Selectable,Drawable {};

int main()
{
    std::vector<std::unique_ptr<Drawable>> vec;
    for (int i = 0; i < 5; ++i) {
        vec.push_back(std::make_unique<Derived>());
    }
    Selectable* selected = dynamic_cast<Selectable*>(vec[2].get());

    vec.erase(std::remove_if(vec.begin(),vec.end(),[selected](auto&& ptr) { 
            return ptr.get() == dynamic_cast<Drawable*>(selected); 
    }),vec.end());
}

显然,如果我选择是Drawable的指针,一切都很好,但这不是我的意图.

我得到运行时错误导致程序崩溃.为什么会发生这种情况,我该如何解决

解决方法

关键问题在于std :: remove_if“删除”元素的方式:

Removing is done by shifting (by means of move assignment) the
elements in the range in such a way that the elements that are not to
be removed appear in the beginning of the range. Relative order of the
elements that remain is preserved and the physical size of the
container is unchanged. Iterators pointing to an element between the
new logical end and the physical end of the range are still
dereferenceable,but the elements themselves have unspecified values
(as per MoveAssignable post-condition).

所以基本上,你保留一个由ptr = vec [2] .get()获取的原始指针,但是没有人保证ptr保持有效.您只能保证vec [2]有效. (过滤之前曾经在vec [2]中的唯一指针位于新的逻辑端和物理端之间,以未指定的值).

在你的例子中,当std :: remove_if到达第三个元素时,谓词返回true,remove_if调用vec [2] .get()的析构函数.因为你保留一个原始的指针,你使用的指针已经被破坏的对象.

猜你在找的Java相关文章