Gå til innhold

Dynamisk array i en klasse


Anbefalte innlegg

Hei!

 

Jobber med følgende oppgave:

Lag en klasse kalt Matrix, den skal inneholde lagringsplass for M*N tall av typen double.

 

Når vi skal bestemme hvordan vi skal lagre dataene i klassen er det lurt å vite hvordan

vi skal bruke dataene siden. I matriseoperasjoner kommer vi til å referere til elementene

basert på rad og kolonne. Derfor er det nyttig å ordne medlemmene i matrisen som en

tabell. I tillegg kommer vi til å ha behov for å forandre størrelsen på dataene vi har lagret

i matrisen, derfor bør tabellen være dynamisk allokert.

 

Lag følgende konstruktører for matrisen:

 

Matrix()

• Default-konstruktør, skal initialisere matrisen til den ugyldige tilstanden.

 

explicit Matrix(unsigned int N)

• Skal konstruere en gyldig NxN-matrise, initialisert som identitetsmatrisen. (explicitnøkkelordet dekkes ikke av pensum, men bør brukes her).

 

Matrix(unsigned int M, unsigned int N)

• Skal konstruere en gyldig MxN-matrise, initialisert som 0-matrisen. (Alle elementer lik 0)

 

~Matrix()

• Destruktøren til Matrix, skal frigi/slette alt dynamisk allokert minne.

 

Dette er hva jeg har hittil av kode:

Header

class Matrix{
private:
 typedef double* matrix;
 matrix *mat;
public:
 Matrix();
 explicit Matrix(int N);
 Matrix(int M, int N);
 double getValue(int M, int N) const;
 void setValue(int M, int N, double value);
 ~Matrix();
};

 

main-fil

#include <iostream>
#include "Matrix.h"
#include <cstdlib>
using namespace std;

Matrix::Matrix(){
*mat = NULL;
}

Matrix::Matrix(int N){
*mat = new double[N];
for (int i = 0; i < N; i++)
 mat[i] = new double[N];
for (int i = 0; i < N; i++){
 for (int j = 0; j < N; j++){
  if (i == j)
mat[i][j] = 1;
  else
mat[i][j] = 0;
 }
}
}

Matrix::Matrix(int M, int N){
*mat = new double[M];
for (int i = 0; i < N; i++)
 mat[i] = new double[N];
for (int i = 0; i < M; i++){
 for (int j = 0; j < N; j++){
  mat[i][j] = 0;
 }
}
}

Matrix::~Matrix(){
delete *mat;
}

double Matrix::getValue(int M, int N) const{
return mat[M][N];
}

void Matrix::setValue(int M, int N, double value){
mat[M][N] = value;
}

 

Har jeg gått riktig frem for å lage et dynamisk array? Vil slike simple get- og set-funksjoner fungere nå som arrayet er dynamisk? Er det riktig måte å lage en destruktor på?

Lenke til kommentar
  • 2 måneder senere...
Videoannonse
Annonse

Har jeg gått riktig frem for å lage et dynamisk array? Vil slike simple get- og set-funksjoner fungere nå som arrayet er dynamisk? Er det riktig måte å lage en destruktor på?

 

Ingen av konstruktørene dine vil fungere. F.eks i Matrix(int N, int M) så allokerer du plass for M, og så forsøker å allokere plass for N for hver N. Dette hadde forsåvidt fungert hvis du har brukt en dobbeltpeker, e.g **mat, og hvis du hadde iterert opp til M for hver allokering med størrelse N, sånn at hver peker har pekt til et eget minneområde for hver rad. Hva hvis N > M i den for loopen din ? Du må derfor allokere mat med N*M. Når du forsøker å sette alle verdiene til 0, så indekserer du matrisa som om det var et todimensjonalt array. Du må skille mellom en og to dimensjonale arrays. Det virker som du forveksler dimensjonene til matrisa med arrayet. For en matrise der du bruker en enkeltpeker, så må du altså indeksere denne med matrise. Du kan ta høyde for at matrisa egentlig er todimensjonal ved f.eks : row*width + column e.l for indeksen i en get/set funksjon med row og column som parametere. Dvs de get/set funksjonene dine vil ikke fungere. Destruktøren din er også feil. Riktig syntaks for å deallokere minneområde til mat er : delete [] mat.

Lenke til kommentar

Wow, wow, hold your horses littegran nå, Daisuke. Konstruktørene er litt føkka som de er nå, men det kan fikses forholdsvis kjapt ved å bytte ut

 

*mat = new double[N];

 

... med noe sånt som

 

mat = new matrix[N];

.

 

Default-konstruktøren din er helt skækk (jeg ser at oppgaveteksten krever at den skal være der og at den initialiserer matrisen til en state som er på trynet - som du førvrig klarer helt fint - men, det bryter ganske kraftig med f.eks. RAII-idiomet som kan anses som et himmelsendt programmeringsidiom).

 

Hvis ikke jeg husker helt feil (orker ikke å sjekke det opp nå), så kan du ikke allokere multidimensjonale arrays "helt dynamisk" (du er avhengig av at dimensjonen til alle bortsett fra den siste kan bestemmes compile-time mener jeg å huske). Derfor er det en helt kurrant måte du gjør allokeringa på her.

 

Hvis du skal leke sykt seriøs her, så er det en fordel å allokere alle de m * n elementene på én gang som Daisuke foreslår pga. at programmet da gjerne kan bli mer cache-effektivt, men det er liksom ikke der du begynner optimeringsprosessen.

 

Jeg kjeda meg litt her, så jeg haxxa sammen noe drit her bare for gøy. Den er litt kulere enn klassen din i og med at jeg bruker templates samt en proxy-klasse for å få den digge vi-chillern-med-et-todimensjonalt-array-følelsen her, men da kan den kanskje fungere litt som inspirasjon uten at dritten er klin lik det du skal lage.

 

#include <iostream>
#include <algorithm>

template<typename T>
class matrix {
class proxy_elem {
public:
	proxy_elem(T* r) : row(r) { }

	T& operator[](int j)
	{
		return row[j];
	}

	operator const T*() const
	{
		return row;
	}

private:
	T* row;
};

public:
matrix(int m, int n) : m(m), n(n), data(new T*[m])
{
	for (int i = 0; i < m; ++i) {
		data[i] = new T[n];
		std::fill_n(data[i], n, 0);
	}
}

~matrix()
{
	for (int i = 0; i < m; ++i) {
		delete[] data[i];
	}
	delete[] data;
}

proxy_elem operator[](int i)
{
	return proxy_elem(data[i]);
}

private:
T** data;
size_t m, n;
};

int main(int argc, char* argv[])
{
using namespace std;

matrix<double> m(2, 2);
for (int i = 0; i < 2; ++i) {
	m[i][i] = 1;
}

for (int i = 0; i < 2; ++i) {
	for (int j = 0; j < 2; ++j) {
		cout << m[i][j] << " ";
	}
	cout << endl;
}

return 0;
}

  • Liker 2
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...