0

这是我做所有高级操作的主要工人阶级:

class Image
{
public:
    Image();
    Image(const Image& copy);
    ~Image();

    void loadimage(string filename);
    void saveimage(string filename);
    Image superimpose(const Image& ontop, Color mask);

    int getwidth();
    int getheight();
    Image operator=(const Image&);

protected:    
    vector< vector<Color> > pixels;
    int width;
    int height;
    ImageLoader* loader;
};

它有一个复制构造函数:

Image::Image(const Image& copy)
{
    width = copy.width;
    height = copy.height;
    loader = copy.loader;

    pixels = copy.pixels;
}

和一个重载的 operator= 方法:

Image Image::operator=(const Image& other)
{   
    width = other.width;
    height = other.height;
    loader = other.loader;

    pixels = other.pixels

    // Return this instance
    return *this;
}

析构函数是:

Image::~Image()
{
    delete loader;
}

loadimage() 方法创建了一个新的动态分配的加载器来显示:

if(magic_number == "P3")
{
    loader = new P3Loader;
}
else if (magic_number == "P6")
{
    loader = new P6Loader;
}
else
{
    exit(1);  // If file is of an inappropriate format
}

当我运行程序时,它挂起。

编辑: 该帖子已被编辑以反映问题。请参阅解决问题的 Praetorian 解决方案。

4

1 回答 1

2

您尚未发布Image::loader成员如何初始化,但我假设它是这样的:

Image::Image()
: loader(nullptr)
{
  // do stuff
  // then initialize loader
  loader = new ImageLoader(...);
}

同样,~Image()缺少 的定义,所以我做出另一个假设:

Image::~Image()
{
  delete loader;
}

在复制构造函数(和赋值运算符)中,您只需从另一个Image对象复制指针,以便两个loader成员现在都指向同一个ImageLoader对象。当第一个对象的析构函数运行时,它将delete是该ImageLoader对象,然后第二个对象的析构函数将再次尝试delete相同的对象。这种双重删除是未定义的行为,可能是您的程序崩溃的原因。

您需要ImageLoader在复制构造函数和赋值运算符中制作对象的深层副本。它可能看起来像这样:

loader = new ImageLoader(*other.loader); // invokes ImageLoader's copy ctor
于 2013-05-26T02:30:43.693 回答