3

这是我正在使用的代码的简化版本:

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:在调用“std::_List_iterator > > std::list >::erase(std::_List_const_iterator > >)”时,对象“iter”的切片作为实际参数 2 传递由于隐式类型转换

我相信这基本上是说我正在导致隐式类型转换:

iter = p_entities.erase(iter);

(注意:即使我将代码更改为: p_entities.erase(iter++); 也会收到相同的警告)

我不太明白我在上面“切片”的是什么。这到底是什么意思,我应该如何解决这个警告?我宁愿稍微复杂的代码也不愿完全关闭警告消息。

4

3 回答 3

1

看起来您的std::list::erase()方法需要 astd::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() );
于 2012-11-29T06:42:35.940 回答
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());
于 2012-11-29T08:27:48.603 回答
0

经过大约一个月的其他工作,我意识到问题的答案基本上是在改变

std::list::迭代器

std::list::const_iterator

发生切片是因为 .erase() 需要一个 const_iterator 并从迭代器进行隐式转换。

我建议在标题中使用 typedef ing std::list 以涵盖未来可能的类型更改。

不过,我保留了 MatthieuM. 的答案,因为我认为对象切片的定义比这个答案本身有用得多。

于 2012-12-26T06:33:34.210 回答