2014-12-08 2 views
-1

Я новичок в C++. У меня проблема с обработкой изображений. То, что я пытаюсь сделать, - написать мой класс Image, который имеет в качестве частных переменных горизонтальные и вертикальные размеры изображения и данных для каждого пикселя (полутоновый, только 2D-массив поплавков). Я также написал основные функции внутри класса: getPixel, SetPixel, GetSize, GetData (возвращает 2D-массив данных).Деструктор и перегруженный = оператор для класса изображения

Мой вопрос: Я читал, что для лучшей производительности я должен написать функцию деструктора и перегрузить оператор «=» как минимум.

1) Может кто-нибудь объяснить, почему мне это действительно нужно (до тех пор, пока эта версия работает более или менее).

2) Можете ли вы написать деструктор и оператор «=» для меня? Я думаю, это не сложно для экспертов, я пытался один раз, но с моим деструктором у меня были ошибки памяти: Ошибка _BLOCK_TYPE_IS_VALID (pHead-> nBlockUse);

Обновление: Даже сейчас, без определения оператора «=», я могу использовать его в своей основной функции. Если, скажем, у меня был Image img1 размера (1x1) и img2 размера (2x2), я могу написать img1 = img2, и он работает!

Update2: После того, как я пытался реализовать простой деструктор (удалить [] пикс) ошибка "_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; 
    } 
}; 

UPDDATE 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

Используйте 'зОго :: вектора ' вместо 'Pixel *' 'для pix' и вам тоже не нужно писать. –

+0

Но это работает. Почему вектор лучше? – Mihon

+0

Потому что 'std :: vector' будет управлять памятью для вас, и вам не нужно беспокоиться об удалении, изменении размера, распределении новых буферов при создании копии и т. Д. –

ответ

0

Вы спросили:

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

Вы выделения памяти для pix в конструкторе. Вам нужно реализовать деструктор, который освобождает память. Я не вижу, чтобы один из них был реализован в вашем классе.

~Image() 
{ 
    delete [] pix; 
} 

Как только вы добавляете код в деструктор для освобождения ресурсов, которые были приобретены в классе в какой-то момент в своей жизни время, The Rule of Three вступает в игру, и вы должны реализовать конструктор копирования и оператор присваивания для бесплатного кода с ошибкой.

Оператор присваивания будет выглядеть примерно так:

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

После того, как я вставил ваш деструктор, ошибка« _BLOCK_TYPE_IS_VALID (pHead-> nBlockUse) ". – Mihon

+0

Вам также понадобится реализовать конструктор копирования. Не уверен, сделали ли вы это. –

+0

Я попытался реализовать все, как в правиле трех. Все еще есть ошибка. Я написал его в обновлении 3 по моему вопросу. – Mihon

0

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

Это уже ответил здесь: https://stackoverflow.com/a/4172724/2642059 сегмент, который относится к вам:

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.

Как новый C++ кодер лучшее, что я могу сделать для вас, это направить вас от сырых указателей.

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 ответ делает хорошую работу этого. Но я бы советовал вам избавиться от сырого указателя вместо этого, так что я покажу вам, как сделать это:

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

Спасибо! Я постараюсь сделать это сейчас. Я попытался написать деструктор, скопировать и назначить оператор, как в правиле трех, но все же я получил эту ошибку. – Mihon

+0

Это работает! Но здесь функция GetData() должна возвращать 2D-массив ... Но его легко редактировать. – Mihon

+1

'Pixel **' is ** not ** 2D-массив, это указатель на указатель или если он указывает на массив указателем на первый элемент массива указателей. Кастинг от 'Pixel *' до 'Pixel **' приведет к неопределенному поведению. –

Смежные вопросы