c++ - std::remove_if 来自 std::vector 的多态 std::unique_ptr

标签 c++ polymorphism c++14

我有一个包含三个类的层次结构,其中 Derived源自 SelectableDrawable .然后我有一个 std::vectorstd::unique_ptr<Drawable>我用 Derived 填充对象。

确定该 vector 将仅由同时从两个基派生的对象填充。

当我尝试使用指向 Selected 的指针从 vector 中删除某个元素时,问题就来了.

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

显然,如果我制作 selected成为指向 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).

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

在您的示例中,当 std::remove_if 到达第三个元素时,谓词返回 true 并且 remove_if 调用 vec[ 2].get() 的析构函数。 因为你保留了一个指向它的原始指针,所以你正在使用一个指向已经被销毁的对象的指针。

关于c++ - std::remove_if 来自 std::vector 的多态 std::unique_ptr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43706186/

相关文章:

java - 如何在构造函数中创建给定类型的新对象

c++ - 如何在 C++ 中重复访问数组和 vector 的元素?

c++ - 在 C++ 中,命名参数的范围是否包括其默认值的表达式?

c++ - 我的程序找不到boost库

polymorphism - Laravel 5 与数据透视表的多态关系

c++ - 无法构建支持 Windows 应用商店的 C++ 库

java - 数组有问题,无法向他添加任何内容

c++ - 类型类方法的参数推导(由 const 限定符重载)在 gcc 中以尾随返回类型失败,但在 clang 中没有

c++ - 为什么 std::function 不能与完美转发一起使用?

c++ - openCV 2.4.9 与 CUDA 6.5 的编译错误