使用std::vector.push_back()与用户定义类型的正确方法

3

我目前使用vector.push_back()方法时遇到了分割错误(我认为是这个原因)。

以下是示例代码:

我有一个名为Zombie的类:

class Zombie
{
    public:
       Zombie();
       ~Zombie();

       SDL_Surface* image;

       SDL_Rect box;

       bool dead;

   protected:

   private:
       // gets random coordinates around the screen
       SDL_Rect get_zombie_rect();
 };

构造函数为:

Zombie::Zombie()
   :
   dead(false),
   image(load_image("Player.png")),
   box(get_zombie_rect())
{

}

Zombie有一个处理程序类来管理向量,并使用名为create_new_zombie()的函数。(这里出现了问题)

void Zombie_Manager::create_new_zombie()
{
   Zombie newZombie;
   zombies.push_back(newZombie);
}

这是向向量中添加元素的正确方式吗?

我能够使用指针得到一个可行的版本,但一定有更简单、更正确的方法来完成这个任务,对吗?

如果std::vector.push_back()浅复制其新元素,为什么会出现段错误?我在假设上有错吗?


希望你意识到image是未初始化的垃圾数据。 - John Dibling
如何实现复制构造函数:http://zh.wikipedia.org/wiki/复制构造函数 - user195488
1
可能是“三法则”(Rule of Three)的重复问题。链接:https://dev59.com/eG855IYBdhLWcg3wvXDd。 - fredoverflow
1
我认为并不是每个问题都可以通过另一个问题的答案来回答,这样就算是重复问题了吗? - Chris A.
@Chris:我认为这是当另一个问题是常见问题解答时。 - ildjarn
1个回答

9

你需要实现一个拷贝构造函数和一个赋值运算符。

zombies.push_back(newZombie); 在向量中压入newZombie的副本。当该方法进入时,原始的newZombie被销毁。我打赌在~Zombie()中你会调用delete image;

因为你没有正确的拷贝构造函数和赋值运算符,所有的副本都将是无效的,因为它们将包含悬挂指针。

始终遵循“三法则”-如果你需要实现一个析构函数,那么你也需要实现一个拷贝构造函数和赋值运算符。


2
由于该对象包含原始指针,因此需要进行深层复制。或者更好的方法是使用shared_ptr - Mark Ransom
为什么编译器不为我们实现一个呢? - user195488
2
@0A0D 是的,但它只进行浅复制。拷贝中的指针 image 指向与原始指针相同的位置。所以当原始指针被销毁时,拷贝中的指针将会悬空。 - Luchian Grigore
考虑到这是关于SDL的讨论,我不认为有一个实际的“delete”存在。无论如何,悬空指针确实很可能是问题所在。如果C++11是一个选项,我建议还实现一个移动构造函数,以便能够高效地使用STL容器(而不需要将指针以任何形式存储)。 - eq-

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接