【问题标题】:Problems when looping through a list of pointers - C++循环遍历指针列表时的问题 - C++
【发布时间】:2012-09-18 20:52:16
【问题描述】:

我有一个指向基础抽象类(实体)的指针列表

std::list<Entity*> m_entities;

我已经创建了一个 typedef 用于迭代这个类

typedef std::list<Entity*>::const_iterator entityIter;

然后我尝试遍历列表中的每个指针

for (entityIter i = m_entities.begin(); i != m_entities.end(); ++i)
{
    const Entity &e = *i;    // ERROR
    e.DoStuff();
}

尝试引用每个指针时出现以下错误

IntelliSense:不存在合适的构造函数来将“Entity *const”转换为“Entity”

我做错了什么?

编辑:

我尝试过使用 std::shared_ptr

std::list<std::shared_ptr<Entity>> m_entities;

虽然我不能以这种方式添加到列表中

Entity::Entity(Game *game) 
    : m_game(game)                  
{
    m_game->g_idGenerator->generateNewID();

    m_game->m_entities.push_back(this);      // ERROR
}

使用以下

m_game->m_entities.push_back(std::shared_ptr<Entity>(this));

给我这个错误

错误 C2664: 'void std::list<_ty>::push_back(_Ty &&)' : 无法将参数 1 从 >'Entity' 转换为 'std::tr1::shared_ptr<_ty> &&'

编辑 2:

当前代码摘要

for (entityIter i = m_entities.begin(); i != m_entities.end(); ++i)
{
    // *i dereferences the iterator and returns an Entity*
    // **i would additionally deference the pointer
    // Adding 'const' infront of Entity means that I can't alter the Entity
    Entity &e = **i;

    e.draw(dt);   // Causes access violation error with standard pointers
}   

已尝试转换为 std:shared_ptr 以查看是否可以避免上述代码触发的错误。

但是,我现在无法将实体添加到 std::shared_ptr 列表中

    m_game->m_entities.push_back(std::shared_ptr<Entity>(this));

所以总的来说,我有一个标准指针的访问冲突错误,我不能用 shared_ptr 添加到列表中。

填充列表是通过基础实体类的构造函数完成的

Entity::Entity(Game *game) 
    : m_game(game)                  
{
    m_game->g_idGenerator->generateNewID();

            // shared_ptr version
    m_game->m_entities.push_back(std::shared_ptr<Entity>(this));  // ERROR C2664

            // raw pointer version
            //m_game->m_entities.push_back(this);  // ACCESS VIOLATION ERROR when calling methods
}

【问题讨论】:

  • What have I done incorrectly? - 首先,您使用的是原始指针而不是 std::shared_ptr 之类的东西。
  • @Mihai,这与问题无关。使用原始指针是完全有效的。
  • @PeteFordham 是的,当然,但这肯定会给 OP 造成混乱。另外,从代码的外观来看,这似乎不像是作业,所以我只能希望他不会那样编写生产代码。
  • 能否请您添加如何填充 m_entities 以确保您的指针正确?

标签: c++ pointers loops


【解决方案1】:
const Entity &e = *i;

*i 取消对迭代器的引用并返回一个 Entity*。

**i 会额外服从指针。

为避免保留引用,您可以使用(*i)-&gt;memberFunction(...);

不要忘记,如果您使用operator new 分配实体,您还需要operator delete 他们。

这是一个使用 std::shared_ptr 的示例,因为您的代码看起来很复杂,无法在页面上讨论。

我创建了一个简单的Entity 类并在std::shared_ptr 中使用它。我多次输入相同的std::shared_ptr&lt;Entity&gt; 纯粹是为了演示std::shared_ptr 管理此信息,包括将自身复制到列表中。

#include <memory>
#include <iostream>
#include <string>
#include <list>
using namespace std;

class Entity {
private:
  string name;
public:
  Entity(const std::string& n) :
    name(n)
  { }

  const string& getName() {
    return name;
  }
};

int main(int argc, char** argv) {
  list<shared_ptr<Entity> > l;

  shared_ptr<Entity> sp(new Entity("Repeated!"));

  l.push_back(sp);
  l.push_back(sp);
  l.push_back(shared_ptr<Entity>(new Entity("Foo")));
  l.push_back(sp);
  l.push_back(shared_ptr<Entity>(new Entity("Bar")));
  l.push_back(sp);

  for(list<shared_ptr<Entity> >::const_iterator iter = l.begin();
      iter != l.end(); ++iter)
    {
      cout << ">> " << (*iter)->getName() << endl;
    }
};

注意:将完全相同的原始指针放入多个std::shared_ptr 对象和复制 std::shared_ptr 就像push_back 那样是有区别的。后一种情况由std::shared_ptr 完全管理,而前一种情况下每个std::shared_ptr 都试图独立管理。

【讨论】:

  • 我明白了。谢谢你说清楚。这与 std::shared_ptr 的工作方式相同吗?
  • 我也得到访问冲突读取位置0xccccccd0 当使用引用指针调用任何实体类的方法时?例如。 e.更新(dt);即使使用 typedef std::list::iterator entityIter; 也会发生这种情况
  • 您能否在问题中澄清您正在使用的当前代码(在导致初始问题的原始代码之后)以避免猜测?
【解决方案2】:

选项 A)您想要访问元素并保证您不会更改它们:

typedef std::list<Entity*>::const_iterator entityIter;

std::list<Entity*> m_entities;
for (entityIter i = m_entities.begin(); i != m_entities.end(); ++i)
{
    const Entity &e = **i;    // ERROR
    e.DoStuff();
}

选项 B)您想要访问元素并更改它们:

typedef std::list<Entity*>::iterator entityIter; // no const_

std::list<Entity*> m_entities;
for (entityIter i = m_entities.begin(); i != m_entities.end(); ++i)
{
    Entity &e = **i;    // ERROR
    e.DoStuff();
}

【讨论】:

    猜你喜欢
    • 2013-09-12
    • 2013-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-06
    • 2013-06-22
    相关资源
    最近更新 更多