2017-12-08 8 views
0

Ich versuche, einen Konstruktor, Destruktor und Kopie Konstruktor für eine Matrix-Klasse zu erstellen, und ich bin nicht so sicher, ob ich es gut mache.die Art des Schreibens Konstruktor, Dekonstruktor und Kopie Konstruktor für Matrix-Klasse

Insbesondere bin ich über 2 Dinge nicht sicher:

  1. Ist der destructor des freien Speichers nehme auch für den Speicher, der in dem Kopie-Konstruktor zugeordnet ist?

  2. Was die Zeile Mat[i][j]=other[i][j] betrifft (siehe unten stehenden Code), frage ich mich, ob ich stattdessen schreiben sollte?

class Matrix 
{ 
private: 
    int rows; 
    int cols; 
    int **Mat; 

public: 
    Matrix (const int &rows,const int &cols); 
    Matrix (const Matrix &other); 
    ~Matrix(); 
}; 

Matrix::Matrix(const int &n_rows,const int &n_cols) //constructor of class Matrix 
{ 
    rows=n_rows; 
    cols=n_cols; 
    Mat=new int* [cols]; 

    for(int i =0;i<rows;i++) 
     Mat[i]=new int[cols]; 

    for(int i=0;i<rows;i++) 
     for(int j=0;j<cols;j++) 
     Mat[i][j]=0;    
} 

Matrix::~Matrix() //destructor 
{ 
    for(int i =0;i<rows;i++) 
     delete Mat[i]; 

    delete[] Mat; 
} 

Matrix::Matrix(const Matrix &other) //copy constructor 
{ 
    cols=other.cols; 
    rows=other.rows; 
    Mat=new int* [other.rows]; 

    for(int i =0;i<other.rows;i++) 
     Mat[i]=new int[other.cols]; 

    for(int i=0;i<other.rows;i++) 
     for(int j=0;j<other.cols;j++) 
      Mat[i][j]=other[i][j]; 
} 
+2

Sie wollen auch den Kopierzuweisungsoperator. Siehe [Regel von 3/5/0] (http://en.cppreference.com/w/cpp/language/rule_of_three). –

+0

Verwenden Sie einen Std :: Vektor. –

+0

Ich glaube Francois ging in diese Richtung, aber ich könnte falsch liegen. Um eine tiefe Kopie zu erstellen, müssen Sie den Operator "assignment =" überladen. Ohne eine tiefe Kopie haben Sie eine flache Kopie, die der Destruktor den gesamten mit dieser Instanz assoziierten Speicher freigibt. –

Antwort

0

A Konstruktor ist eine Klasse, Operation, die eine Objektinstanz einer bestimmten Klasse initialisiert.

Die Objekterstellung umfasst mehrere Operationen wie:

  1. Zuweisung von Speicher, die Struktur für das neue Objekt zu speichern
  2. die Attribute des Objekts initialisieren richtig.

A Copykonstruktor ist ein Spezialfall des Konstruktors, die eine Instanz der gleichen Klasse als ein Eingabeparameter annimmt. - Es ist immer noch ein Konstruktor, der die oben erwähnten Operationen ausführt.

Ein Destruktor ist eine Klassenoperation, die für das Finalisieren eines Objekts zuständig ist, wenn es nicht mehr verwendet werden soll.

Ein Objekt kann unter Verwendung eines beliebigen Konstruktors erstellt werden, entweder des gewöhnlichen Konstruktors oder des Kopierkonstruktors. Wenn Sie das Objekt löschen, sollte der von Ihrer Klasse zugewiesene Speicher im Destruktor aufgehoben werden.

Hoffe, das hilft.

Wie für Ihre Code Frage; Wenn Sie einen Kopierkonstruktor aufrufen, übergeben Sie eine vorhandene Objektinstanz der Klasse. Da Sie keine Operatorüberladung implementiert haben, greifen Sie auf die Eigenschaft des Objekts zu, wie Sie in # 2 gesagt haben.

Ich bin nicht sicher, ob dies Ihre Fragen vollständig beantwortet, aber ich hoffe es hilft.

0

1) Ich denke, Dekonstruktor löscht nur Objekt, das gehört, weil Kopie-konstruierte Objekte ihren eigenen Destruktor haben.

2) Ja, Mat[i][j] = other.Mat[i][j] ist richtig, aber wenn Sie wollen, dass Ihr Programm etwas schneller ist, versuchen Sie es mit Zeigern (es ist nicht einfach zum ersten Mal, ich weiß, aber wenn man sich daran gewöhnt ist nicht das schwer ^^)

+0

Ich verstehe immer noch nicht ... Beabsichtigt Destruktor, den Speicher auch im Copy-Konstruktor freizugeben? –

+0

Copy-Konstruktor ist nur ein überladener "normaler" Konstruktor, also erstellt er ein Objekt auf die gleiche Weise wie ein "normaler" Konstruktor. – Soveu

0
  1. Ja. Alles, was das Objekt noch zugewiesen hat, sollte im Destruktor freigegeben werden. Es spielt keine Rolle, welcher Konstruktor es zugewiesen hat.

  2. Ja, Sie müssen verwenden, insbesondere, weil Sie für Ihre Klasse keine operator[] definiert haben.

Sie müssen auch eine Kopie Zuweisungsoperator hinzuzufügen, pro der "Rule of Three", die im Grunde heißt es:

Wenn eine Klasse eine benutzerdefinierte destructor erfordert, eine benutzerdefinierte Copykonstruktor oder ein benutzerdefinierter Kopierzuweisungsoperator erfordert fast alle drei.

Versuchen Sie folgendes:

class Matrix 
{ 
private: 
    int rows; 
    int cols; 
    int **Mat; 

public: 
    Matrix (int n_rows, int n_cols); 
    Matrix (const Matrix &other); 
    ~Matrix(); 

    Matrix& operator=(const Matrix &rhs); 
    // alternatively: 
    // Matrix& operator=(Matrix rhs); 
}; 

Matrix::Matrix(int n_rows, int n_cols) 
{ 
    rows = n _rows; 
    cols = n_cols; 

    Mat = new int*[rows]; 
    for(int i = 0; i < rows; ++i) 
    { 
     Mat[i] = new int[cols]; 
     for(int j = 0; i < cols; ++j) 
      Mat[i][j] = 0; 
    } 
} 

Matrix::Matrix(const Matrix &other) 
{ 
    rows = other.rows; 
    cols = other.cols; 

    Mat = new int*[rows];  
    for(int i = 0; i < rows; ++i) 
    { 
     Mat[i] = new int[cols]; 
     for(int j = 0; j < cols; ++j) 
      Mat[i][j] = other.Mat[i][j]; 
    } 
} 

Matrix::~Matrix() 
{ 
    for(int i = 0; i < rows; ++i) 
     delete Mat[i]; 
    delete[] Mat; 
} 

Matrix& Matrix::operator=(const Matrix &rhs) 
{ 
    if (&rhs != this) 
    { 
     Matrix temp(rhs); 
     std::swap(Mat, temp.Mat); 
     std::swap(rows, temp.rows); 
     std::swap(cols, temp.cols); 
    } 

    return *this; 
} 

// alternatively: 
/* 
Matrix& Matrix::operator=(Matrix rhs) 
{ 
    std::swap(Mat, rhs.Mat); 
    std::swap(rows, rhs.rows); 
    std::swap(cols, rhs.cols); 
    return *this; 
} 
*/ 

Eine bessere Lösung ist nicht new[]/delete[] direkt überhaupt zu benutzen. Verwenden Sie std::vector statt und lassen Sie es alles für Sie erledigt, so dass Ihre Klasse der „Rule of Null“ folgen:

Klassen, die benutzerdefinierten Destruktoren, Kopieren/Verschieben Bauer oder kopieren/verschieben Zuweisungsoperator haben sollte ausschließlich beschäftigen mit Besitz (was aus der Single Responsibility Principle folgt). Andere Klassen sollten keine benutzerdefinierten Destruktoren, Copy/Move-Konstruktoren oder Kopier-/Verschiebe-Zuweisungsoperatoren haben.

class Matrix 
{ 
private: 
    std::vector<std:vector<int> > Mat; 

public: 
    Matrix (int n_rows, int n_cols); 
}; 

Matrix::Matrix(int n_rows, int n_cols) 
{ 
    Mat.resize(n_rows); 
    for(int i = 0; i < n_rows; ++i) 
     Mat[i].resize(n_cols, 0); 

    /* alternatively: 
    Mat.resize(n_rows, std::vector<int>(n_cols, 0)); 
    */ 
} 
Verwandte Themen