-1

I am new in C++. I have a problem with Image Processing. What I am trying to do is to write my class Image, which has as private variables horizontal and vertical sizes of an image and data for each pixel (grayscale, just 2D array of floats). I also wrote basic functions within the class: getPixel,SetPixel, GetSize, GetData (returns 2D array of data).

My question is: I read, that for best performance I have to write a destructor function and overloaded "=" operator at least.

1) Can someone explain why I really need it (as long as this version working more or less).

2) Can you write destructor and "=" operator for me? I guess, it is not difficult for experts, I tried once but with my destructor I got memory errors: Error _BLOCK_TYPE_IS_VALID(pHead->nBlockUse);

Update: Even now, without defining "=" operator, I can use it in my main function. If, say, I had Image img1 of size (1x1) and img2 of size (2x2), I can write img1=img2, and it works!

Update2: After I tried to implement simple destructor (delete [] pix) the error "_BLOCK_TYPE_IS_VALID" appeared

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;
    }
};

UPDDATE 3: I tried to implement everything from rule of three. I added:

~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;
}

Still got memory error: "_BLOCK_TYPE_IS_VALID..."

Mihon
  • 125
  • 1
  • 9

2 Answers2

0

You asked:

1) Can someone explain why I really need it (as long as this version working more or less).

You are allocating memory for pix in the constructor. You need to implement a destructor that deallocates the memory. I don't see one implemented in your class.

~Image()
{
   delete [] pix;
}

As soon as you add code in the destructor for releasing resources that were acquired by the class at some point in its life time, The Rule of Three comes into play and you'll have to implement the copy constructor and assignment operator for a bug free code.

The assignment operator will look something like:

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;
}
Community
  • 1
  • 1
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • After I inserted your destructor, the error "_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)" arrised again. – Mihon Dec 08 '14 at 19:55
  • You'll need to implement the copy constructor too. Not sure whether you did that. – R Sahu Dec 08 '14 at 19:58
  • I tried to implement everything like in rule of three. Still got a error. I wrote it in update 3 on my question. – Mihon Dec 08 '14 at 20:10
  • The line `pix = that.pix;` is wrong in the copy constructor. You need to copy the values from `that.pix` just like I showed in the `operator=` function. Just replace `rhs` by `that`. – R Sahu Dec 08 '14 at 20:39
0

1) Can someone explain why I really need it (as long as this version working more or less).

Is already answered here: https://stackoverflow.com/a/4172724/2642059 The segment that pertains to you is:

Most of the time, you do not need to manage a resource yourself, because an existing class such as std::string already does it for you. Just compare the simple code using a std::string member to the convoluted and error-prone alternative using a char* and you should be convinced. As long as you stay away from raw pointer members, the rule of three is unlikely to concern your own code.

As a new C++ coder the best thing I can do for you is steer you away from raw pointers.

2) Can you write destructor and "=" operator for me? I guess, it is not difficult for experts, I tried once but with my destructor I got memory errors: Error _BLOCK_TYPE_IS_VALID(pHead->nBlockUse);

R Sahu's answer does a good job of this. But I'd advise you to get rid of your raw pointer instead, so I'll show you how to do that:

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
    }
};
Community
  • 1
  • 1
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • Thanks! I'll try do to it now. I tried to write destructor, copy and assign operator as in rule of three, but still I got this error. – Mihon Dec 08 '14 at 20:10
  • That is working! But here GetData() function is supposed to return 2D array... But it is easy to edit. – Mihon Dec 08 '14 at 20:29
  • 1
    `Pixel**` is **not** a 2D array, it's a pointer to a pointer or if it's "pointing to an array" a pointer to the first element of an array of pointers. Casting from `Pixel*` to `Pixel**` will result in undefined behavior. – Captain Obvlious Dec 08 '14 at 20:52
  • @МихаилМихайловичГенкин OK, I'm scared if you think it's "easy to edit." I'd suggest you look at some of StackOverflows other questions on indexing a 1D array as a 2D array, and if they are unclear maybe you could ask a new question about that? – Jonathan Mee Dec 08 '14 at 20:58