我正在为我的编程课制作一款模拟双向飞碟射击的游戏。
主Game
类包含 std::vector<Bullet> bullets
, 其中Bullet
是我的类(class)。它只包含具体类型的成员,并覆盖基类 Drawable
类来绘制和更新自身。它不会重新定义任何运算符。在每一帧,bullets
循环遍历,并更新和绘制每个项目符号。
当用户按下某个键时,我添加了一个 Bullet
至 bullets
像这样:
在游戏中::handleInput:
if (ui.isSpaceBar())
{
Bullet newBullet = rifle.fire();
addBullet(newBullet);
}
rifle.fire
返回 Bullet
像这样:
Bullet Rifle :: fire()
{
... calculation of position and velocity...
return Bullet(...position and velocity values...);
}
和addBullet
看起来像这样:
void addBullet(const Bullet & newBullet)
{
bool assigned = false;
for (int i = 0; i < bullets.size(); i++)
{
// If the i'th bullet is off-screen or hit something ...
if (bullets[i].isDead())
{
// ... then overwrite it with the new bullet,
// instead of using push_back, to avoid constantly
// increasing the size of the vector
bullets[i] = newBullet;
assigned = true;
break;
}
}
if (!assigned)
bullets.push_back(newBullet);
}
我的问题是关于 bullets[i] = newBullet;
行的.我需要 delete
在使用索引器覆盖 vector 中的值之前有什么?如果我理解正确,使用值而不是指针( Bullet
而不是 Bullet *
和 return Bullet(...)
而不是 return new Bullet(...)
)意味着我永远不必调用 delete
, 和 Bullet
实例超出范围时会自动销毁,这将是 vector 超出范围时。是对的吗?如果是这样,是否使用 vector 的索引器运算符 delete
旧值(在这种情况下是“死”子弹)?如果没有,我错过了什么?我应该使用指针而不是值吗?
最佳答案
当您使用具体对象(例如 Bullet
)而不是指向对象的指针时,您不需要使用 delete。
因此 bullets[i] = myBullet
复制了 myBullet
。它将 bullets[i]
的旧值赋给 myBullet
的新值。当 vector 超出范围时,它将调用它的每个元素析构函数,该析构函数清除元素持有的所有内存。
为了在技术上正确,上述语句使用赋值运算符 (operator=
) 来进行复制。这会执行清理旧的 bullet
并将新的 bullet 的
成员变量复制到旧的 bullet 的
成员变量所需的一切。
bullets.push_back(myBullet)
类似。除了它将 myBullet
添加到 vector 的末尾。所以这意味着如果 vector 的大小为 9,那么它现在将为 10。
从技术上讲,push_back
使用复制构造函数而不是赋值运算符来构造新对象(我认为),因为不存在旧的 bullet
对象。
底线是,给定一个正确实现的具体类(无论它在内部有多复杂),您可以在 std::vector
中使用它们的实例,而不用担心进行任何内存清理。
关于c++ - 载体如何清理自己? (或者他们呢?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33747248/