C++对象删除崩溃
C++ object deletion crashing
我试图包含所有可能导致这些问题的必要代码。
程序第二次崩溃这段代码是运行:
for (int i = 0; i < player.projectiles.size(); i++)
{
bool temp = player.projectiles[i].move(begin, WIDTH);
if (temp == true)
{
player.projectiles[i].destroy();
player.projectiles.erase(player.projectiles.begin() + i);
}
}
Player.projectiles 是来自 class 射弹的对象向量。
成员函数 move 完美运行,函数 destroy 如下所示:
void Projectile::destroy()
{
delete this;
}
第一次循环 运行 一切正常,但第二次我的程序崩溃了,我不明白为什么。我怀疑这与删除对象有关。非常感谢任何帮助。
您没有在 vector
中存储 Projectile*
指针 ,您存储的是实际 Projectile
对象(您的循环正在使用 operator.
而不是 operator->
访问 Projectile
class 的成员这一事实就证明了这一点)。因此,对这些对象中的任何一个调用 destroy()
绝对是错误的做法,因为您不拥有该内存! vector
会,因此当对象从 vector
中移除时,会为您销毁每个对象,包括当 vector
被清除或销毁自身时。
话虽这么说,你也在修改 player.projectiles
的同时遍历它,所以你的循环至少会 跳过元素 因为元素正在被删除,并且 甚至可以 出界。您不得在调用 erase()
的迭代中增加 i
计数器,例如:
for (size_t i = 0; i < player.projectiles.size(); )
{
if (player.projectiles[i].move(begin, WIDTH))
player.projectiles.erase(player.projectiles.begin() + i);
else
++i;
}
或者,vector::erase()
returns 一个 迭代器 到被擦除元素之后的下一个元素,所以让你的循环使用迭代器而不是索引,例如:
for(auto iter = player.projectiles.begin(); iter != player.projectiles.end(); )
{
if (iter->move(begin, WIDTH))
iter = player.projectiles.erase(iter);
else
++iter;
}
或者,您可以使用 erase-remove idiom via std::remove_if()
替换整个循环,例如:
#include <algorithm>
player.projectiles.erase(
std::remove_if(player.projectiles.begin(), player.projectiles.end(),
[=](auto &projectile) { return projectile.move(begin, WIDTH); }
),
player.projectiles.end()
);
或者,在 C++20 中 std::erase_if()
:
std::erase_if(
player.projectiles,
[=](auto &projectile) { return projectile.move(begin, WIDTH); }
);
我试图包含所有可能导致这些问题的必要代码。 程序第二次崩溃这段代码是运行:
for (int i = 0; i < player.projectiles.size(); i++)
{
bool temp = player.projectiles[i].move(begin, WIDTH);
if (temp == true)
{
player.projectiles[i].destroy();
player.projectiles.erase(player.projectiles.begin() + i);
}
}
Player.projectiles 是来自 class 射弹的对象向量。 成员函数 move 完美运行,函数 destroy 如下所示:
void Projectile::destroy()
{
delete this;
}
第一次循环 运行 一切正常,但第二次我的程序崩溃了,我不明白为什么。我怀疑这与删除对象有关。非常感谢任何帮助。
您没有在 vector
中存储 Projectile*
指针 ,您存储的是实际 Projectile
对象(您的循环正在使用 operator.
而不是 operator->
访问 Projectile
class 的成员这一事实就证明了这一点)。因此,对这些对象中的任何一个调用 destroy()
绝对是错误的做法,因为您不拥有该内存! vector
会,因此当对象从 vector
中移除时,会为您销毁每个对象,包括当 vector
被清除或销毁自身时。
话虽这么说,你也在修改 player.projectiles
的同时遍历它,所以你的循环至少会 跳过元素 因为元素正在被删除,并且 甚至可以 出界。您不得在调用 erase()
的迭代中增加 i
计数器,例如:
for (size_t i = 0; i < player.projectiles.size(); )
{
if (player.projectiles[i].move(begin, WIDTH))
player.projectiles.erase(player.projectiles.begin() + i);
else
++i;
}
或者,vector::erase()
returns 一个 迭代器 到被擦除元素之后的下一个元素,所以让你的循环使用迭代器而不是索引,例如:
for(auto iter = player.projectiles.begin(); iter != player.projectiles.end(); )
{
if (iter->move(begin, WIDTH))
iter = player.projectiles.erase(iter);
else
++iter;
}
或者,您可以使用 erase-remove idiom via std::remove_if()
替换整个循环,例如:
#include <algorithm>
player.projectiles.erase(
std::remove_if(player.projectiles.begin(), player.projectiles.end(),
[=](auto &projectile) { return projectile.move(begin, WIDTH); }
),
player.projectiles.end()
);
或者,在 C++20 中 std::erase_if()
:
std::erase_if(
player.projectiles,
[=](auto &projectile) { return projectile.move(begin, WIDTH); }
);