图像类的析构函数和重载 = 运算符

Destructor and overloaded= operator for Image class

本文关键字:重载 运算符 析构函数 图像      更新时间:2023-10-16

我是C++新手。我在图像处理方面有问题。我正在尝试做的是编写我的类 Image,它具有图像的水平和垂直大小以及每个像素的数据(灰度,只是浮点数的 2D 数组(作为私有变量。我还在类中编写了基本函数:getPixel,SetPixel,GetSize,GetData(返回2D数据数组(。

我的问题是:我读到,为了获得最佳性能,我必须至少编写一个析构函数和重载的"="运算符。

1(有人可以解释为什么我真的需要它(只要这个版本或多或少地工作(。

2(你能为我写析构函数和"="运算符吗?我想,这对专家来说并不难,我尝试过一次,但使用我的析构函数我遇到了内存错误:错误_BLOCK_TYPE_IS_VALID(pHead->nBlockUse(;

更新:即使是现在,无需定义"="运算符,我也可以在我的主函数中使用它。如果,比如说,我有大小 (1x1( 的图像 img1 和大小 (2x2( 的 img2,我可以写 img1=img2,它可以工作!

更新2:在我尝试实现简单的析构函数(删除[] pix(后,出现错误"_BLOCK_TYPE_IS_VALID">

struct Pixel
{
    float p;
};
struct size
{
    int x;
    int y;
};
class Image {
private:
   int _x, _y;
   Pixel *pix;
public:
    Image(int x, int y){
        pix = new Pixel[x * y];
        _x = x;
        _y = y;
    }
    float getPixel(int i, int j) {
        return pix[i * _y + j].p;
    }
    void setPixel(int i, int j, Pixel val)
    {
        pix[i * _y + j].p = val.p;
    }
    size GetSize(){
        size a;
        a.x = _x;
        a.y = _y;
        return a;
    }
    Pixel **GetData(){
        Pixel **a=0;
        a = new Pixel*[_x];
        for (int i = 0; i < _x; i++){
            a[i] = new Pixel[_y];
            for (int j = 0; j < _y; j++){
                a[i][j] = pix[i*_y + j];
            }
        }
        return a;
    }
};

更新日期 3:我试图实现三法则中的所有内容。我补充说:

~Image()
{
    delete[] pix;
}
Image(const Image& that)
{
    pix = new Pixel[that._x*that._y];
    pix = that.pix;
    _x = that._x;
    _y = that._y;
}
Image& operator=(const Image& that)
{
    if (this != &that)
    {
        delete[] pix;
        pix = new Pixel[that._x*that._y];
        pix = that.pix;
        _x = that._x;
        _y = that._y;
    }
    return *this;
}

仍然出现内存错误:"_BLOCK_TYPE_IS_VALID...">

你问:

1(有人可以解释为什么我真的需要它(只要这个版本或多或少地工作(。

您正在为构造函数中的pix分配内存。您需要实现一个解除分配内存的析构函数。我没有看到在您的类中实现一个。

~Image()
{
   delete [] pix;
}

一旦您在析构函数中添加代码以释放类在其生命周期中的某个时间点获取的资源,三法就会发挥作用,您必须为无错误代码实现复制构造函数和赋值运算符。

赋值运算符将如下所示:

Image& operator=(Image const& rhs) {
    // Don't do anything for self assignment, such as a = a;
    if ( this != &rhs )
    {
       delete [] pix;
       _x = rhs._x;
       _y = rhs._y;
       pix = new Pixel[_x * _y];
       for ( int i = 0; i < _x*_y; ++i )
       {
          pix[i] = rhs.pix[i]
       }
    }
    return *this;
}

1(有人可以解释为什么我真的需要它(只要这个版本或多或少地工作(。

这里已经回答了:https://stackoverflow.com/a/4172724/2642059与您相关的细分是:

大多数情况下,您不需要自己管理资源,因为现有的类(如 std::string(已经为您完成了这项工作。只需将使用 std::string 成员的简单代码与使用 char* 的复杂且容易出错的替代代码进行比较,您应该会被说服。只要你远离原始指针成员,三法则就不太可能与你自己的代码有关。

作为一名新的C++程序员,我能为你做的最好的事情就是引导你远离原始指针。

2(你能为我写析构函数和"="运算符吗?我想,这对专家来说并不难,我尝试过一次,但使用我的析构函数我遇到了内存错误:错误_BLOCK_TYPE_IS_VALID(pHead->nBlockUse(;

R Sahu的回答在这方面做得很好。但我建议你去掉你的原始指针,所以我会告诉你如何做到这一点:

struct Pixel
{
    Pixel() : p(0.0f) {} // Create a default constructor for Pixel so it can be used in a vector
    float p;
};
class Image {
private:
   int _x, _y;
   std::vector<Pixel> pix; // This is your new array
public:
    Image(int x, int y) :
        pix(x * y) // This is called the constructor initializer list and that's where you construct member objects.
    {
        _x = x;
        _y = y;
    }
    float getPixel(int i, int j) {
        return pix[i * _y + j].p;
    }
    void setPixel(int i, int j, Pixel val)
    {
        pix[i * _y + j].p = val.p;
    }
    size GetSize(){
        size a;
        a.x = _x;
        a.y = _y;
        return a;
    }
    const Pixel* GetData(){ // We're going to pass back the vector's internal array here, but you should probably just return a const vector
        return pix.data(); // We're returning this as read only data for convenience any modification to the data should be done through the Image class
    }
};