在一个作用域中推送五个对象指针,然后检查对象的布尔值是否为 false,会给出错误
Pushing five object pointers in one scope, then checking if the bool of the object is false, gives an error
我正在为我的大学项目开发一个游戏,遇到了指针问题。我有一个子弹矢量,可以检查每颗子弹是否有碰撞。但是,当我尝试一次生成 5 颗子弹(霰弹枪射击)时,它会正确生成所有内容,然后我浏览矢量并检查子弹是否还活着。由于某种原因,它会找到 NULL 指针或指针的损坏数据。如果有人知道如何解决这个问题,将不胜感激。谢谢!
项目符号检查:
void Bullet::checkOutOfRange()
{
if(type == "enemy_bullet")
{
if(body->GetPosition().x <= -10.0f)
{
alive = false;
}
}
// checks if the body is out of the window size
else if (body->GetPosition().x > 510.0f || body->GetPosition().x < -10.0f || body->GetPosition().y > 291.0f || body->GetPosition().y < -10)
{
alive = false;
}
}
子弹碰撞检测:
class MyContactListener : public b2ContactListener
{
void BeginContact(b2Contact* contact) override
{
if (contact && contact->IsTouching())
{
Entity* A = static_cast<Entity*>(contact->GetFixtureA()->GetBody()->GetUserData());
Entity* B = static_cast<Entity*>(contact->GetFixtureB()->GetBody()->GetUserData());
//------
if((A->type == "player_bullet" && B->type == "enemy") || (A->type == "enemy" && B->type == "player_bullet"))
{
Bullet *bullet = nullptr;
Enemy *other = nullptr;
if (A->type == "player_bullet" && B->type == "enemy")
{
bullet = dynamic_cast<Bullet*>(A);
other = dynamic_cast<Enemy*>(B);
}
else if (A->type == "enemy" && B->type == "player_bullet")
{
bullet = dynamic_cast<Bullet*>(B);
other = dynamic_cast<Enemy*>(A);
}
if ((A && B) || (B&&A))
{
other->bodySprite.set_animation("death");
bullet->alive = false;
other->alive = false;
}
}
}
}
}
游戏中的子弹检查:
for (auto itr = player_bullets.begin(), itrEnd = player_bullets.end(); itr != itrEnd; ++itr)
{
(*itr)->checkOutOfRange(); // go to declaration to see where the bullets stop
(*itr)->bodySprite.set_position((*itr)->body->GetPosition().x, (*itr)->body->GetPosition().y);
(*itr)->bodySprite.set_rotation((*itr)->bulletDir * 180 / PI);
(*itr)->moveBullet(20.0f);
if ((*itr)->alive == false)
{
input_world->DestroyBody((*itr)->body);
delete *itr;
itr = player_bullets.erase(itr);
}
}
霰弹枪射击生成:
void spawnShotgunShot(float x, float y, float dir, b2World *world)
{
// maybe bad pointer management?
Bullet *bullet_ptr1 = new Bullet(x, y, dir, world, "player_bullet", PLAYER_BULLET, ENEMY);
player_bullets.push_back(bullet_ptr1);
Bullet *bullet_ptr2 = new Bullet(x, y, dir + 0.5, world, "player_bullet", PLAYER_BULLET, ENEMY);
player_bullets.push_back(bullet_ptr2);
Bullet *bullet_ptr3 = new Bullet(x, y, dir + 0.25, world, "player_bullet", PLAYER_BULLET, ENEMY);
player_bullets.push_back(bullet_ptr3);
Bullet *bullet_ptr4 = new Bullet(x, y, dir - 0.5, world, "player_bullet", PLAYER_BULLET, ENEMY);
player_bullets.push_back(bullet_ptr4);
Bullet *bullet_ptr5 = new Bullet(x, y, dir - 0.25, world, "player_bullet", PLAYER_BULLET, ENEMY);
player_bullets.push_back(bullet_ptr5);
}
这是一个包含 sln 的测试版本: 链接到测试构建
您的问题是检查项目符号的循环中的itrEnd
变量。 在循环开始时将其初始化为player_bullets.end()
,然后检查itr != itrEnd
作为循环条件。 但是,当您从向量中擦除项目符号时,这会在擦除的迭代器(包括结束迭代器)之后使迭代器失效。 您将继续使用矢量的原始结束迭代器,而不是基于其较小尺寸的新迭代器。
删除itrEnd
变量,只需检查itr != player_bullets.end()
作为循环条件。 这将确保您始终使用"当前"结束迭代器,即使它由于元素被擦除而更改。
在相关说明中,当您从向量中删除元素时,从erase
调用中返回的迭代器将用于被擦除的元素之后的元素。 在下一次迭代开始时,循环的++itr
将前进到该元素之外,然后再次检查循环条件。 这意味着每当您从矢量中删除项目符号时,您的循环都会"跳过"它之后的项目符号。 如果最后一个项目符号被删除,循环将"跳过"结束迭代器并继续迭代到向量的末尾。
有关如何解决此问题的信息,请参阅此 SO 问题。
相关文章:
- 当一个新对象被分配到它的地址时,对象是否必须被销毁
- 在这种情况下,java对象是否可以调用本机函数
- 堆分配的对象是否存在永不为空的唯一所有者?
- QFileSystemModel 对象是否会被删除?
- 具有相同特征的两个对象是否只在内存中存储一次?无论定义它们的函数是什么,都是不同的
- 内联函数的函数本地静态对象是否在共享对象文件之间共享?
- 临时C++对象是否为左值?
- 为什么复制构造函数不需要检查输入对象是否指向自身?
- "this"指向的对象是否与 const 对象相同?
- 有什么方法可以检测我的类的对象是否在堆栈上创建
- 基类对象是否隐式添加到派生类中?
- 当 T 具有非平凡析构函数时,类类型 T 的对象是否可以常量初始化?
- 如何检查指针后面的对象是否有效或已删除?
- 谷神星求解器:残差函子使用的可变对象是否良好实践?还有什么其他选择
- 单一实例对象是否通过线程安全返回shared_ptr
- 对象是否保证在调用其成员函数之前被初始化
- 在另一个对象 B 中创建对象 A 时,对象 A 是否是对象 B 的本地对象,对象 A 是否会存在于对象 B 的实例化之外?
- 如何确定对象是否已分配成员
- 我们如何在c 中序列化或应对类的对象.是否有任何预定义的库
- 友元类对象是否可以在其成员函数中访问派生类对象的基类私有成员?