对象切片和隐式类型转换

时间:2012-11-29 06:12:43

标签: c++ type-conversion

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

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 ++),我也会收到相同的警告;)

我不太明白我在上面所说的“切片”。 这究竟是什么意思以及我应该如何解决这个警告?我的代码比完全关闭警告信息更令人费解。

3 个答案:

答案 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。的答案,因为我认为对象切片的定义比这个答案本身更有用。