Деструктор шаблона вызывается в конце конструктора класса шаблона - PullRequest
1 голос
/ 09 апреля 2020

У меня возникли проблемы с классом шаблона, над которым я работаю. Вот определение моих классов (я сохранил только основные части, из которых возникает ошибка): Sampler.h

#ifndef SAMPLER_H
#define SAMPLER_H

#include "matrix.h"
#include "MatrixOperations.h"

template <class T>
class Sampler
{
      public:
             virtual T getnumber()=0;
};

const Matrix ZEROS = zeros_mat(1,1);
const Matrix UNIT = unit_mat(1);

class NormalSampler_multi:public Sampler<Matrix>
{
   public:
           virtual Matrix getnumber();
           NormalSampler_multi(Matrix m=ZEROS, Matrix VarCovar=UNIT);
           void printMean();
           void printVar();
   private:
            Matrix mu;
            Matrix var;


};
#endif


И файл cpp: Sampler.cpp

#include "Sampler.h"
#include"matrix.h"
#include "MatrixOperations.h"

#include<iostream>
#include<cstdlib>
#include<cmath>
using namespace std;

NormalSampler_multi::NormalSampler_multi(Matrix m, Matrix VarCovar){
    if(m.get_nbColumns()>1 && m.get_nbRows()>1){
        cout << "The mean should be a 1d-matrix\n";
        exit(EXIT_FAILURE);
    }
    if(VarCovar.isSymmetric()==false){
        cout << "The Variance-Covariance matrix should be symmetric\n";
        exit(EXIT_FAILURE);
    }
    mu = m;
    var = VarCovar;
}

void NormalSampler_multi::printMean(){mu.print_matrix();}
void NormalSampler_multi::printVar(){var.print_matrix();}


Matrix NormalSampler_multi::getnumber(){//Not implemented yet};

Вот моя проблема. Когда я запускаю следующий код: main.cpp

#include <iostream>
#include <math.h>
#include <cstdlib>
#include <time.h>
using namespace std;

#include "matrix.h"
#include "MatrixOperations.h"
#include "Sampler.h"

int main(){

    //Vector of means
    Matrix mean(5,1);
    for(int i=0;i<5;i++){
        mean(i,0) = i;
    }

    //Creation of the multidimensional sampler
    NormalSampler_multi Z(mean, variance);
    cout << "Print of the mean after assignment:" << endl;
    Z.printMean();
    cout << "Print of the variance after assignment" << endl;
    Z.printVar();
    return 0;

}

Значения mu и var не совпадают со значениями mean и variance (как и должно быть) , Когда я изучил его, я обнаружил, что деструктор класса Matrix вызывается в конце конструктора NormalSampler_multi. Поэтому я думаю, что он удаляет значения mu и sigma, но я действительно не понимаю, почему и как это решить.

(Основная часть) класса Matrix определена ниже: Matrix.h

#ifndef MATRIX_H
#define MATRIX_H


class Matrix{
public:
    Matrix(int nbRows=0, int nbColumns=0); 
    Matrix(const Matrix& a); 
    ~Matrix(); 

    //Access to elements
    double& operator()(int i, int j);  

    int get_nbRows(void) const;
    int get_nbColumns(void) const;

    //Useful functions
    void print_matrix(void);

protected:
    int n; //Number of rows
    int p; //Number of columns
    double **pt; //Pointer to elements

};

#endif // MATRIX_H

и их реализация: Matrix.cpp

#include "matrix.h"
#include "MatrixOperations.h"
#include <iostream>
#include <cstdlib>
#include <math.h>
#include <cmath>
using namespace std;

Matrix::Matrix(int nbRows, int nbColumns){
    n = nbRows;
    p = nbColumns;
    pt = new double*[n];
    for(int i=0; i<n; i++){
        pt[i] = new double[p];}
    //Initialize the array to 0
    for(int i=0; i<n; i++){
        for(int j=0; j<p; j++){
            pt[i][j] = 0;
        }
    }
}

Matrix::Matrix(const Matrix& a){
    n = a.n;
    p = a.p;
    pt = new double*[n];
    for(int i=0; i<n; i++){
        pt[i] = new double[p];
        for(int j=0; j<p; j++){
            pt[i][j] = a.pt[i][j];
        }
    }

}

Matrix::~Matrix(){
    cout << "destructor called\n";
    delete[] pt;}

int Matrix::get_nbRows(void) const {return n;}
int Matrix::get_nbColumns(void) const {return p;}


double &Matrix::operator()(int i, int j){
    if ((i < 0)||(i>=n)||(j < 0)||(j>=p))
    {
        cout << "Index out of bounds! \n";
        exit(EXIT_FAILURE);
    }
    return pt[i][j];
}

//Print a matrix on the console
void Matrix::print_matrix(void){
    cout << "[";
    for(int i=0; i<n; i++){
            cout << "[";
        for(int j=0; j<p; j++){
            cout << (*this)(i,j);
            if(j<p-1){cout  << ",";}
        }
        cout << "]";
        if(i<n-1){cout << ",\n";}
        else{}
    }
    cout << "]\n";
    cout << endl;
}

Спасибо!

1 Ответ

0 голосов
/ 09 апреля 2020

NormalSampler_multi(Matrix m, Matrix VarCovar) { - параметры m и VarCovar будут уничтожены при завершении конструктора.

Ваши проблемы могут быть связаны с тем, что Matrix не подчиняется правилу 3/5 / 0 . Сгенерированный по умолчанию оператор присваивания, вызываемый mu = m; var = VarCovar;, выполняет членское присваивание, и это портит ваши инварианты класса. В итоге вы получите mu.pt == m.pt, а затем, когда m будет уничтожен, mu.pt будет висящим указателем.

Простое решение для этого - заменить pt на vector<vector<double>>, а затем ваш класс будет соответствовать правилу нуля. В качестве альтернативы вы можете реализовать правильный оператор присваивания.

(Сноска - могут быть и другие проблемы, это была одна из тех, которые выделялись).

...