Dubbi su costruttori copia e operatori di assegnazione

di Anonimizzato20721 il
12 risposte
Salve a tutti, ho dei problemi riguardo il file .cpp che a quanto pare mi crea un loop infinito, forse non ho capito bene come allocare la memoria dinamicamente e l'uso dei distruttori e costruttori, in particolare non mi torna il il getPixel, il costruttore di copia e l'operatore di assegnazione, l'obiettivo dell'esercizio sarebbe proprio di sapersi destreggiare con quest'ultimi, grazie in anticipo a chi risponderà

ecco il testo
-si completi il codice del costruttore BitmapImage facendo in modo che se una delle dimensioni fornite dall'immagine è nulla o negativa allora la dimensione è impostata a 1
-si completi il distruttore per evitare memory teak
-si implementi il metodo getPixel in modo tale che se vengono richiesti pixel al di fuori delle dimensioni dell'immagine si renda un pixel i cui valori RGB sono (-1,-1,-1)
-si implementi costruttore di copia
-si implementi operatore di assegnazione
-si implementi un operatore di uguaglianza





FILE .h
#ifndef BITMAPIMAGE_H_
#define BITMAPIMAGE_H_

#include "RGBPixel.h"

class BitmapImage {
public:
	BitmapImage(int w, int h); // TODO check that w and h are >0. Minimum image size is 1x1
	BitmapImage(const BitmapImage& bm); // TODO implement a copy constructor
	virtual ~BitmapImage(); // TODO avoid memory leaks

	void setPixel(int x, int y, const RGBPixel& value);
	RGBPixel getPixel(int x, int y) const; // TODO: getting pixels outside of image return a RGBPixel with values (-1, -1, -1)

	bool operator==(const BitmapImage& rh); // TODO: implement
	BitmapImage& operator=(const BitmapImage& rh); // TODO implement an assignment operator

	int getWidth() const {
		return width;
	}
	int getHeight() const {
		return height;
	}

protected:
	int width, height;
	RGBPixel* bitmap;
};

#endif /* BITMAPIMAGE_H_ */


FILE .cpp
#include "BitmapImage.h"

BitmapImage::BitmapImage(int w, int h) : width(w), height(h) {
	// TODO check that w and h are >0. Minimum image size is 1x1
	if(w <= 0 && h <= 0) {
        width = 1;
        height = 1;
    }
    bitmap = new RGBPixel[width * height];
}

BitmapImage::~BitmapImage() {
	// TODO avoid memory leaks
	if(bitmap != nullptr)
	    delete[] bitmap;
}

// TODO implement a copy constructor
BitmapImage::BitmapImage(const BitmapImage& bm) {
    //shallow copy
    width = bm.width;
    height = bm.height;
    //deep copy
    if(bm.bitmap != nullptr){
        bitmap = new RGBPixel(*bm.bitmap);
        for (int i = 0; i < width * height; i++)
            bitmap[i] = bm.bitmap[i];
    }
    else
        bitmap = nullptr;
}


void BitmapImage::setPixel(int x, int y, const RGBPixel& value) {
	if ((x >= 0) && (x < width) && (y >= 0) && (y < height))
		bitmap[x + y * width] = value;
}

RGBPixel BitmapImage::getPixel(int x, int y) const {
	// TODO: getting pixels outside of image return a RGBPixel with values (-1, -1, -1)
    if ((x >= 0) && (x < width) && (y >= 0) && (y < height))
        return  bitmap[x + y * width];
    else
        return RGBPixel(-1,-1,-1);
}

// TODO implement an equality operator
bool BitmapImage::operator==(const BitmapImage& rh) {
    if(width != rh.width)
	    return false;
    if(height != rh.height)
        return false;
    //devo controllare anche tutto l'array bitmap
    for(int i = 0; i < width*height; i++)
        if(bitmap[i] != rh.bitmap[i])
            return false;
    return true;
}

// TODO implement an assignment operator
BitmapImage& BitmapImage::operator=(const BitmapImage& rh) {
    if(this != &rh){
        if(bitmap != nullptr)
            delete []bitmap;

        width = rh.width;
        height = rh.height;

        if(rh.bitmap != nullptr) {
            bitmap = new RGBPixel(*rh.bitmap);
            for (int i = 0; i < width * height; i++)
                bitmap[i] = rh.bitmap[i];
        }
        else
            bitmap = nullptr;
    }
	return *this;
}


12 Risposte

  • Nel costruttore di copia e operatore assegnamento questa riga
    
    bitmap = new RGBPixel(*bm.bitmap);
    
    non ha senso. Dev'essere
    
    bitmap = new RGBPixel[witdh * height];
    
    come nel costruttore.
  • Ok perfetto, adesso mi torna il costruttore di copia e l'operatore di assegnazione e dovrebbe andare bene.

    Ho ancora problemi col costruttore per quanto riguarda la richiesta "check that w and h are >0. Minimum image size is 1x1" i

    ll file di tester mi dice hint: your code/tests do not correctly cover constructor: "check that height is >0. Minimum image size is 1x1", a me sembra sia giusto come ho fatto
  • La condizione è vera se e solo se sia w sia h sono <= 0.
    Questo significa che se w > 0, il compilatore non perde tempo a verificare se anche h > 0, quindi la condizione è falsa e tu corri il rischio di avere una w > 0 e una h <= 0.
    Le due condizioni devono essere verificate separatamente.
  • Grazie per la risposta e per i consigli.
    Ho usato OR che fa sì che valga quando rispetta una delle due condizioni o entrambe, ma non torna lo stesso.
    il test mi restituisce "hint: your code/tests do not correctly cover constructor: check that width is >0. Minimum image size is 1x1"
    potrebbe essere che non stia inizializzando bene l'immagine 1x1?
    
    BitmapImage::BitmapImage(int w, int h) : width(w), height(h) {
    	// TODO check that w and h are >0. Minimum image size is 1x1
        if (w  < 0 || h < 0) {
            width = 1;
            height = 1;
        }
        bitmap = new RGBPixel[width * height];
    }
  • Posto w == 0 e h == 10, la condizione diventa:
    if (0 < 0 || 10 < 0)
    ...

    ora 0 < 0 è vero o falso?
  • Direi falso.
    Mi sono accorto di essermi dimenticato l'uguale, la condizione deve essere <= di zero.
    ho messo l'uguale ma non torno comunque, mi ridà lo stesso suggerimento il tester
  • Premesso che esistono diversi modi per soddisfare la condizione, può darsi che il tester verifichi che le variabili poste a condizione siano proprio width e height, non w e h. Oppure che verifichi il verso dell'uguaglianza.
    Prova a scriverlo nel modo più bovino possibile.
    
    BitmapImage::BitmapImage(int w, int h) : width(w), height(h) {
       // TODO check that w and h are >0. Minimum image size is 1x1
       if (width > 0 && height > 0) 
           bitmap = new RGBPixel[width * height];
       else {
           width = 1;
           height = 1;
           bitmap = new RGBPixel[width * height];
       }
    }
    
  • Grazie per le risposte date fino ad ora
    Ho provato il codice, l'ho riprovato in altri modi analoghi ma niente, forse il problema è il discorso dell'immagine 1x1?
    oppure potrebbero esserci altro errore nel codice
  • Difficile dare una risposta se non si conosce questo fantomatico file di tester o test o quel che è.
    Per quel che posso ancora supporre può darsi (oltre al resto) che al tester non vada a genio la constructor initializer list
    
    BitmapImage::BitmapImage(int w, int h) : width(w), height(h) // questa
    
    ma richieda uno specifico assegnamento dentro il costruttore.
    A ogni modo il costruttore che ti ho postato è corretto.
    Per quanto riguarda l'immagine 1 x 1 è perfettamente legale creare un array (o matrice) di dimensione unitaria.
    Per la getPixel() invece cosa non ti torna?
  • Sulla funzione get non ero sicurissimo andasse bene ma ragionandoci l'ho capita, per quanto riguarda il costruttore ho fatto un mini test di prova mettendo un main che prova a istanziare vari vettori bitmap e a contare con sizeof il numero di elementi degli array, ma sembra non tornare

    nel .cpp
    BitmapImage::BitmapImage(int w, int h) {
    	// TODO check that w and h are >0. Minimum image size is 1x1
        if (w  > 0 && h > 0) {
            width = w;
            height = h;
        }else{
            width = 1;
            height = 1;
        }
        std::cout<< "" << width << endl;
        std::cout << ""<< height<<endl;
            bitmap = new RGBPixel[width*height];
        std::cout << "Length of array = " << (sizeof(bitmap)/sizeof(*bitmap)) << std::endl;
    }
    nel main()
    #include "BitmapImage.h"
    #include "RGBPixel.h"
    
    
    int main() {
        BitmapImage *b1 = new BitmapImage(-1,-4);
        BitmapImage *b2 = new BitmapImage(6,5);
        BitmapImage *b3 = new BitmapImage(3,2);
        BitmapImage *b4 = new BitmapImage(8,-1);
        BitmapImage *b5 = new BitmapImage(80,3);
        return 0;
    }
    
    la risposta del compilatore è:


    1
    1
    Length of array = 2
    6
    5
    Length of array = 2
    3
    2
    Length of array = 2
    1
    1
    Length of array = 2
    80
    3
    Length of array = 2

    Process finished with exit code 0


    si vede che i valori di width e height sono a 1 ma la lunghezza dell'array non dovrebbe essere diversa?
    forse sto sbagliando tutto, ma dovrebbe venire il prodotto, quindi 1,30,6,1,240
    grazie ancora delle risposte e del tempo che mi hai dedicato
  • Questa riga non vale per array allocati dinamicamente:
    
    std::cout << "Length of array = " << (sizeof(bitmap)/sizeof(*bitmap)) << std::endl;
    
    ma vale solo con array statici:
    
    RGBPixel boh[16];
    etc...
    
    il motivo è che bitmap è un puntatore la cui dimensione è fissa e vale 4 o 8 a seconda se stai compilando per 32bit o 64bit.
    Questo comporta che il numero di elementi dell'array è qualcosa di cui devi tenere traccia tu. Sempre.
    Non puoi più ricavarla se la perdi.
  • Ok, perfetto grazie mille per tutti i chiarimenti, molto gentile
Devi accedere o registrarti per scrivere nel forum
12 risposte