这是我正在使用的代码的简化版本:
namespace BasketNovel {
void Engine::BuryEntities()
{
std::list<Entity*>::iterator iter = p_entities.begin();
while (iter != p_entities.end())
{
if ( (*iter)->getAlive() == false )
{
delete (*iter);
iter = p_entities.erase( iter ); //.erase returns next element
}
else iter++;
}
}
}
我收到英特尔静态分析的以下警告:
BasketNovel.cpp(567):警告#12221:切换对象“iter”作为实际参数2传递给“std :: _ List_iterator&gt;&gt; std :: list&gt; :: erase(std ::) _List_const_iterator&gt;&gt;)“由于隐式类型转换而发生
我认为这基本上是说我在:
中导致隐式类型转换iter = p_entities.erase(iter);
(注意:即使我将代码更改为:p_entities.erase(iter ++),我也会收到相同的警告;)
我不太明白我在上面所说的“切片”。 这究竟是什么意思以及我应该如何解决这个警告?我的代码比完全关闭警告信息更令人费解。
答案 0 :(得分:1)
您的std::list::erase()
方法似乎期待std::list<Entity*>::const_iterator
,而您传递std::list<Entity*>::iterator
。这可能意味着您正在使用C ++ 11支持编译代码。
一种解决方案是分两步执行删除。首先,使用std::for_each
删除并设置为0
指向不活动对象的指针。
#include <algorithm>
void deleteDead(Entity* e) {
if (e->getAlive()) return;
delete e;
e = 0;
}
std::for_each(p_entities.begin(), p_entities.end(), deleteDead);
其次,使用[erase-remove idiom](erase-remove idiom)删除0
元素。
#include <algorithm>
p_entities.erase(std::remove(p_entities.begin(), p_entities.end(), 0),
p_entities.end() );
答案 1 :(得分:1)
什么是对象切片
对象切片是复制/移动对象的一部分这一事实,这通常发生在Base / Derived夫妇身上:
struct Base { int i; };
struct Derived: Base { int j; };
void slice() {
Derived d = {};
Base b(d); // b is a "sliced" version of `d`
}
并且可能导致肮脏。
这里虽然这只是一个误报......
可以更容易吗?
是的,当然。
// Place to be deleted values at the end
auto const it = std::partition(p_entities.begin(), p_entities.end(),
[](Entity const* e) { return not e or not e->getAlive(); });
// Delete them
std::for_each(it, p_entities.end(), [](Entity const* e) { delete e; });
// Remove them
p_entities.erase(it, p_entities.end());
答案 2 :(得分:0)
经过大约一个月的其他工作,我意识到问题的答案基本上是在改变
的std ::列表:迭代
到
的std ::目录::为const_iterator
切片发生是因为.erase()需要一个const_iterator并从迭代器进行隐式转换。
我建议在标题中输入std :: list来覆盖未来可能的类型更改。
我保留MatthieuM。的答案,因为我认为对象切片的定义比这个答案本身更有用。