Problem z gleboka kopia konstruktora kopiujacego

0

Witam,

Mam problem z prawdlowym zdefiniowaniem konstruktora kopiujacego dla mojej klasy Matrix.

kod klasy Matrix

#include <sstream> // stringstream
#include <iostream> // cout, cerr
#include <fstream> // ifstream
#include <istream>
using namespace std;

class Matrix
{
public:
Matrix()
{
}

Matrix(int sizeR, int sizeC, double* input_data)
{
	cout << "Constructor of the matrix class";
	M = sizeR;
	N = sizeC;
	data = new double[M*N];
	for (int ii=0; ii<M*N; ii++)
		{
			data[ii] = input_data[ii];
		}
}


~Matrix()
{
	cout << "Deconstructor of the matrix class";
	delete [] data;
}

int GetValue(int i, int j) const {return data[i*N+j];}
void SetValue (int i, int j, double val) {data[i*N+j] = val;}

private:
int M;
int N;
double* data;
};

Moja implementacja konstruktora kopiujacego jednak nie dziala

Matrix(const Matrix& ExistingMatrix)
{
	cout << "Copy constructor of the matrix class";
	M = ExistingMatrix.M;
	N = ExistingMatrix.N;
	data = new double[M*N];
	for (int ii=0; ii<M*N; ii++)
		{
			data[ii] = ExistingMatrix.data[ii];
		}

} 

Przy probie tworzenia kopii objektu klasy Matrix uzywajac w/w konstruktora dostaje blad:

Debug error!

Invalid allocation size 4294967295 bytes.

Pomocy!

0

Ustaw breakpoint na wiersz:
data = new double[MN];
i zobacz ile wynosi M
N
tak a propos twój konstruktor kopiujący (zwykły też) oblicza iloczyn MN - MN+2 razy
for (int ii=0; ii<MN; ii++) // iloczyn liczy się na każdym kroku, chyba że kompilator "zauważy" że MN się nie zmienia i coś z tym zrobi.
oblicz to raz przed przydzieleniem:
int size=MN;
poza tym: Matrix(int sizeR, int sizeC, double
input_data)
czyżby planujesz mieć ujemne ilości wierszy/kolumn?

0

Wybacz jesli bede pisal w laicki sposob, ale ciagle sie ucze...

  1. Ustawilem brakepoint prawym klawiszem na lini data = new double[MN]; ale nie podal mi wartosci MN tylko wyskoczyl wczesniej wspomniany blad.(co robie zle?!)
  2. Po sprawdzeniu int size=M*N wynosi 687194768
  3. Nie planuje wartosci ujemnych. Obiekt klasy Matrix ma byc reprezentacja wczesniej wczytanego wymieszanego obrazu ktorego atrybuty to wartosci pixeli (od 0-255). Moim zadaniem bedzie uzycie algorytmu NNS (Nearest Neighbour Search) w celu poskladania go do kupy.
0

masz coś nie tak z wartościami M i N bo chyba próbujesz za dużo zaalokować bajtów. Ja jak próbowałem zaalokować 4294967295 bajtów to wywaliło mi exception bad_alloc

0

Ad 1, ustaw również breakpoint na tym new przy konstruktorze.
Ad 2, rozmiar 687194768 elementów double to prawie 6 GB pamięci, przemyśl jeszcze raz algorytm, może dziel na fragmenty.
Ad 3, jak nie spodziewasz się ujemnych to używaj unsigned zamiast int

0

tak duży rozmiar macierzy, wskazuje na to, że źle zabrałeś się do tego problemu. 687194768 elementów po 8 bajtów dla double do tego to jest jeszcze tworzenie kopi już czegoś istniejącego, czyli: 68719476882=10995116288 daje 10GB.
Założę się, że w większości komórek masz zera, ergo marnujesz mnóstwo pamięci na zapamiętywanie zer.

Ty na pewno potrzebujesz coś co się nazywa macierzą rzadką, czyli masz zapamiętać jedynie niezerowe elementy macierzy.

0

dodam jeszcze ze pracuje z jednowymiarowa tablica. Program ten uzywa funkcji ReadTXT do odczytania obrazu i przeksztalceniu go w jednowymiarowa macierz. Oto kod main:

 // Reads .txt file representing an image of R rows and C Columns stored in filename 
// and converts it to a 1D array of doubles of size R*C
// Memory allocation is performed inside readTXT
double* readTXT(char *fileName, int sizeR, int sizeC);
Matrix CreateMatrix();


int main ()
{
	
	//M and N represent the number of rows and columns in the image,
	//e.g. for task 1: logo_with_noise and logo_shuffled, M = 512, N = 512
	//e.g. for task 2, Cluttered_scene, M = 768, N = 1024
	//e.g. for task 2, Wally_grey, M = 49, N =  36

	int M = 512; int N = 512;

	// input_data is a pointer to a 1D array of M*N doubles stored in heap. Memory allocation is performed 
	// inside readTXT. readTXT will read an image (in .pgm format) of size MxN and will  store the result in input_data.

	double* input_data = 0;
	
	cout << endl;
	cout << "Data from text file -------------------------------------------" << endl;
	
	// .pgm image is stored in inputFileName, change the path in your program appropriately

	char* inputFileName = "logo_shuffled.txt"; 

	input_data = readTXT(inputFileName, M, N);

	Matrix myMatrix = Matrix(M, N, input_data);


	Matrix Matrix2 = CreateMatrix(); //copy constructor test
	
	

	delete [] input_data;
	cin.get();
	return 0;
}

Matrix CreateMatrix()
{
	Matrix NewMatrix;
	return NewMatrix;
}

// Read .txt file with image of size RxC, and convert to an array of doubles
double* readTXT(char *fileName, int sizeR, int sizeC)
{
  double* data = new double[sizeR*sizeC];
  int i=0;
  ifstream myfile (fileName);
  if (myfile.is_open())
  {
	 
	while ( myfile.good())
    {
       if (i>sizeR*sizeC-1) break;
		 myfile >> *(data+i);
         //cout << *(data+i) << ' '; // This line display the converted data on the screen, you may comment it out. 
	     i++;                                                             
	}
    myfile.close();
  }

  else cout << "Unable to open file"; 
  //cout << i;

  return data;
}
0

Witam ponownie

Problem rozwiazany! Okazuje sie ze niepotrzebnie twozylem funkcje do sprawdzenia konstruktora kopiujacego. Zamienilem:

     
Matrix Matrix2 = CreateMatrix(); //copy constructor test
 
 
 
        delete [] input_data;
        cin.get();
        return 0;
}
 
Matrix CreateMatrix()
{
        Matrix NewMatrix;
        return NewMatrix;
}

Na:

     
Matrix Matrix2 = myMatrix; //copy constructor test
 
 
 
        delete [] input_data;
        cin.get();
        return 0;
}

no i wszystko smiga! dziekuje za pomoc!

1 użytkowników online, w tym zalogowanych: 0, gości: 1