我正在为我的编程课制作一个模拟双向飞碟拍摄的游戏。
主Game
类包含std::vector<Bullet> bullets
,其中Bullet
是我的类。它仅包含具体类型的成员,并覆盖基础Drawable
类以绘制和更新自身。它不会重新定义任何运营商。在每一帧,bullets
都会循环,每个项目符号都会被更新和绘制。
当用户按下某个键时,我将Bullet
添加到bullets
,如下所示:
在Game :: 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
任何内容?如果我理解正确,使用值代替指针(Bullet
代替Bullet *
,return Bullet(...)
代替return new Bullet(...)
)意味着我不必使用{ {1}},delete
实例在超出范围时会自动销毁,这将在向量超出范围时进行。是对的吗?如果是这样,使用向量的索引器运算符Bullet
是否使用旧值(在这种情况下,&#34;死&#34;项目符号)?如果没有,我错过了什么?我应该使用指针而不是值吗?
答案 0 :(得分:2)
当您使用具体对象(例如Bullet
)而不是指向对象的指针时,您不需要使用删除。
因此bullets[i] = myBullet
会复制myBullet
。它会将bullets[i]
的旧值指定为myBullet
的新值。当向量超出范围时,它将调用它的每个元素析构函数,它清理元素所拥有的任何内存。
为了在技术上正确,上述语句使用赋值运算符(operator=
)来制作副本。这样做可以清除旧的bullet
并将新的bullet's
成员变量复制到旧的bullet's
成员变量。
bullets.push_back(myBullet)
类似。除了它将myBullet
添加到向量的末尾。这意味着如果向量的大小为9,那么它现在将为10。
为了在技术上正确,push_back
使用复制构造函数而不是赋值运算符来构造新对象(我认为),因为没有现有的旧bullet
对象。
底线是给定一个正确实现的具体类(无论内部有多复杂),您可以在std::vector
中使用它们的实例,而不用担心进行任何内存清理。