我有一个班级
class Invader
{
public:
Invader();
~Invader();
public:
void Init(InvaderTypes invadertype, CIw2DImage *AlienImage);
void Update(float dt);
void Render();
void SetAlienImage(CIw2DImage *image){ ImageAlien = image; }
void setVisible(bool show) { Visible = show; }
bool isVisible() const { return Visible; }
Iw2DSceneGraph::CSprite *AlienSprite;
Iw2DSceneGraph::CAtlas *AlienAtals;
CIw2DImage *ImageAlien;
std::list<Bullet*> *Bullets;
CIwFMat2D Transform; // Transform matrix
bool Visible; // Sprites visible state
bool Canfire;
};
void Invader::Init(InvaderTypes invadertype, CIw2DImage *AlienImage)
{
if (invadertype == InvaderTypes::TOP_ALIEN)
{
//SetAlienImage(AlienImage);
mImageAlien = AlienImage;
// Create EnemyTop atlas
int frame_w = (int)(mImageAlien->GetWidth() / 2);
int frame_h = (int)(mImageAlien->GetHeight());
AlienAtals = new CAtlas(frame_w, frame_h, 2, mImageAlien);
AlienSprite = new CSprite();
AlienSprite->m_X = 0;
AlienSprite->m_Y = 0;
AlienSprite->SetAtlas(AlienAtals);
AlienSprite->m_W = (float)AlienAtals->GetFrameWidth();
AlienSprite->m_H = (float)AlienAtals->GetFrameHeight();
AlienSprite->m_AnchorX = 0.5;
AlienSprite->SetAnimDuration(2);
}
else if (invadertype == InvaderTypes::MIDDLE_ALIEN)
{
}
else if (invadertype == InvaderTypes::LAST_ALIEN)
{
}
Visible = true;
Bullets = new std::list<Bullet*>();
Canfire = true;
}
Invader::Invader()
{
}
Invader::Invader(const Invader&other)
{
AlienAtals = new CAtlas();
AlienSprite = new CSprite();
*AlienAtals = *other.AlienAtals;
*AlienSprite = *other.AlienSprite;
}
我尝试通过以下方式初始化它:
list<Invader> *invaders = new list<Invader>();
int spacing = 10;
for (int i = 0; i < 5; i++)
{
Invader invader;
invader.Init(TOP_ALIEN, gameResources->getAlienImageTop());
invader.AlienSprite->m_X = 50 + spacing;
invaders->push_back(invader);
spacing += 50;
}
将对象入侵者推送到列表后,最后入侵者列表保存未初始化的指针。所有的指针都丢失了引用。我想知道为什么 ?
答案 0 :(得分:2)
我认为问题出在~Invader()
中。让我们简化示例:
struct A {
int* p;
A() { p = new int(42); }
~A() { delete p; }
};
A
只管理一个指针。当A
超出范围时,该指针将被删除。现在,当我们这样做时会发生什么:
list<A> objs;
{
A newA;
objs.push_back(newA);
// newA deleted here
}
// objs has one element... but its pointer has been deleted!
问题是复制A
(push_back()
执行)只执行浅拷贝:我们复制指针。但由于A
管理自己的内存,我们需要执行深副本。那就是:
A(const A& rhs)
: p(new int(*(rhs.p)))
{ }
这样,复制的A
赢了双删除相同的指针。使用C ++ 11,只需:
struct A {
std::shared_ptr<int> p;
A() { p = std::make_shared<int>(42); }
~A() = default; // this line not even necessary
};
此处,复制A
将复制shared_ptr
,A
的两个副本都将有一个有效的对象指向。如果您不能使用C ++ 11,您仍然可以使用boost::shared_ptr<T>
来满足所有内存管理需求。如果你不能使用它,那么你必须编写一个复制构造函数来完成所有指针元素的完整副本。
或者,最简单的解决方案是让你的容器有指针:
list<A*> objs;
objs.push_back(new A);
然后&#34;浅拷贝&#34;是正确的做法,你需要做的就是记住delete
最后容器中的所有内容。
答案 1 :(得分:0)
您的列表包含Invader
个对象。将它们存储在列表中时,将调用Invader
复制构造函数,并将变量invader
的副本存储在list
中。
除非你定义一个拷贝构造函数,否则它将是默认的对象的浅拷贝。这可能不是你想要的。您应该编写一个显式的复制构造函数,以确保正确复制Invader
。
另一种解决方案是使用Invader
关键字动态分配new
个对象,并在列表中存储指针。如果您这样做,请务必确保在完成后在列表中的delete
对象上调用Invader
。