析构函数和重载=映像类的运算符 我是C++新手。我在图像处理方面有问题。我试图做的是编写我的类Image,它具有图像的水平和垂直大小以及每个像素的数据(灰度,只是二维浮点数数组)的私有变量。我还在类中编写了基本函数:getPixel、SetPixel、GetSize、GetData(返回2D数据数组)

析构函数和重载=映像类的运算符 我是C++新手。我在图像处理方面有问题。我试图做的是编写我的类Image,它具有图像的水平和垂直大小以及每个像素的数据(灰度,只是二维浮点数数组)的私有变量。我还在类中编写了基本函数:getPixel、SetPixel、GetSize、GetData(返回2D数据数组),c++,class,destructor,C++,Class,Destructor,我的问题是:我读到,为了获得最佳性能,我必须至少编写一个析构函数和重载“=”运算符 1) 有人能解释一下为什么我真的需要它(只要这个版本或多或少能工作) 2) 你能为我写析构函数和“=”运算符吗?我想,这对专家来说并不难,我试过一次,但用我的析构函数我得到了内存错误:错误_BLOCK_TYPE_是有效的(pHead->nBlockUse) 更新:即使现在,没有定义“=”操作符,我也可以在我的主函数中使用它。如果,比如说,我有大小为1x1的图像img1和大小为2x2的图像img2,我可以写img1

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

1) 有人能解释一下为什么我真的需要它(只要这个版本或多或少能工作)

2) 你能为我写析构函数和“=”运算符吗?我想,这对专家来说并不难,我试过一次,但用我的析构函数我得到了内存错误:错误_BLOCK_TYPE_是有效的(pHead->nBlockUse)

更新:即使现在,没有定义“=”操作符,我也可以在我的主函数中使用它。如果,比如说,我有大小为1x1的图像img1和大小为2x2的图像img2,我可以写img1=img2,并且它可以工作

Update2:在我尝试实现简单析构函数(delete[]pix)之后,出现了错误“\u BLOCK\u TYPE\u IS\u VALID”

仍然存在内存错误:“\u块\u类型\u有效…”

您询问:

1) 有人能解释一下为什么我真的需要它(只要这个版本或多或少能工作)

您正在为构造函数中的
pix
分配内存。您需要实现一个释放内存的析构函数。我在你们班上没有看到一个

~Image()
{
   delete [] pix;
}
一旦您在析构函数中添加代码以释放类在其生命周期的某个时间点获取的资源,代码就开始发挥作用,您必须为无bug代码实现复制构造函数和赋值运算符

赋值运算符将类似于:

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;
}
Image和operator=(Image const和rhs){
//不要为自我分配做任何事情,例如a=a;
如果(此!=&rhs)
{
删除[]pix;
_x=右侧;
_y=rhs.\U y;
pix=新像素[x*y];
对于(整数i=0;i<\ux*\uy;++i)
{
pix[i]=rhs.pix[i]
}
}
归还*这个;
}
1) 有人能解释一下为什么我真的需要它(只要这个版本或多或少能工作)

这里已经回答了: 与您相关的部分是:

大多数情况下,您不需要自己管理资源,因为诸如std::string之类的现有类已经为您管理了资源。只要将使用std::string成员的简单代码与使用char*的复杂且容易出错的代码进行比较,您就会确信只要远离原始指针成员,三的规则就不太可能涉及到您自己的代码。

作为一个新的C++程序员,我能做的最好的事情就是引导你远离原始指针。 2) 你能为我写析构函数和“=”运算符吗?我想,这对专家来说并不难,我试过一次,但用我的析构函数我得到了内存错误:错误_BLOCK_TYPE_是有效的(pHead->nBlockUse)

奥巴马的回答很好地说明了这一点。但我建议您去掉原始指针,因此我将向您展示如何做到这一点:

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
    }
};
struct像素
{
Pixel():p(0.0f){}//为Pixel创建默认构造函数,以便在向量中使用它
浮动p;
};
阶级形象{
私人:
整数x,y;
std::vector pix;//这是您的新数组
公众:
图像(整数x,整数y):
pix(x*y)//这称为构造函数初始值设定项列表,在这里可以构造成员对象。
{
_x=x;
_y=y;
}
浮点getPixel(整数i,整数j){
返回pix[i*_y+j].p;
}
void setPixel(int i,int j,Pixel val)
{
pix[i*_y+j].p=val.p;
}
大小GetSize(){
尺寸a;
a、 x=x;
a、 y=_y;
返回a;
}
const Pixel*GetData(){//我们将在这里传回向量的内部数组,但您可能只需要返回一个const向量
return pix.data();//为了方便起见,我们将其作为只读数据返回。对数据的任何修改都应该通过Image类完成
}
};

对于
pix
使用
std::vector
而不是
Pixel*
,您也不必编写。但这是可行的。为什么vector更好?因为
std::vector
将为您管理内存,您不必担心删除它、调整它的大小、在复制时分配新的缓冲区等。在我插入析构函数后,错误“\u BLOCK\u TYPE\u is\u VALID(pHead->nBlockUse)”再次出现。您也需要实现复制构造函数。我不确定你是否那样做了。我试着实现像三法则一样的一切。仍然有一个错误。关于我的问题,我在更新3中写了它错误。您需要从
that.pix
复制值,就像我在
操作符=
函数中显示的那样。只需将
rhs
替换为
that
。谢谢!我现在就试着去做。我试着按照第三条规则编写析构函数、复制和分配运算符,但仍然出现了这个错误。这是有效的!但这里GetData()函数应该返回2D数组。。。但它很容易编辑。
Pixel**
不是2D数组,它是指向指针的指针,如果它“指向数组”,则是指向指针数组第一个元素的指针。从
Pixel*
Pixel**
的转换将导致未定义的行为。@МаааМаааачаааачааааааааа,如果他们不清楚,也许你可以问一个新问题?
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;
}
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
    }
};