我确定向量只能由同时来自两个基地的对象填充.
当我尝试通过使用指向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的指针,一切都很好,但这不是我的意图.
解决方法
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()的析构函数.因为你保留一个原始的指针,你使用的指针已经被破坏的对象.