2010-12-07 35 views
5

J'applique ma propre classe de matrice en C++ pour m'aider à développer ma compréhension du langage. J'ai lu quelque part que si vous avez un opérateur + =, utilisez-le dans votre opérateur +. Alors, est ce que j'ai:Opérateur C++ + et opérateur + = surcharge

template <class T> 
const Matrix<T>& Matrix<T>::operator+(const Matrix<T> &R){ 

    Matrix<T> copy(*this); 
    return copy += R; 
} 

Et voici le + = surcharge de l'opérateur:

template <class T> 
const Matrix<T>& Matrix<T>::operator+=(const Matrix<T> & second_matrix){ 
    //Learn how to throw errors.... 
    if (rows != second_matrix.getNumRows() || cols != second_matrix.getNumCols()){throw "Dimension mismatch.";} 
    int i,j; 
    for (i = 0; i < rows; i++){ 
     for (j = 0; j < cols; j++){ 
      data[i][j] += second_matrix.get(i,j); 
     } 
    } 
    return *this; 
} 

je peux utiliser les + = très bien (par exemple, a + = b; renvoie pas des erreurs). Mais appeler l'opérateur + (par exemple, a = b + c;) retourne:

test.cpp.out(77055) malloc: *** error for object 0x300000004: pointer being freed was not allocated 

Juste pour être complet, voici mon destructor:

template <class T> 
Matrix<T>::~Matrix(){ 
    for (int i = 1; i < rows; i++){ 
     delete[] data[i]; } 
    delete[] data; 
} 

J'utilise C++ pour quelques années et off, et ont toujours du mal à garder la trace des pointeurs. J'espère que c'est normal ... Toute aide serait géniale. Merci!

EDIT: voici mon constructeur de copie. Il a été configuré pour libérer les tableaux de données, mais j'ai supprimé cela. maintenant je reçois des fautes de segmentation.

template <class T> 
Matrix<T>::Matrix(const Matrix<T>& second_matrix){ 

    rows = second_matrix.getNumRows(); 
    cols = second_matrix.getNumCols(); 
    data = new T*[rows]; 

    int i,j; 
    for (i = 0; i < rows; i++){ 
     data[i] = new T[cols]; 
    } 
    for (i = 0; i < rows; i++){ 
     for (j = 0; j < cols; j++){ 
      data[i][j] = second_matrix.get(i,j); 
     } 
    } 

} 
+3

À quoi ressemble votre constructeur de copie? C'est probablement votre problème, puisque l'erreur indique que la mémoire est libérée deux fois. –

+0

@Walt W: Oui, je soupçonne que c'est un gros problème. –

+1

@Fred: qu'est-ce qu'un gros problème? – jakev

Répondre

18

operator+() ne devrait pas retourner un type de référence est une nouvelle instance (déclarée localement) qui détient le résultat de l'opération.

+4

+1: Vous renvoyez une référence à un objet (la copie Matricielle) qui est immédiatement détruit lorsque la pile est déchargée; Les références C++ ne sont pas les mêmes que les références Java/C#/etc. –

1

S'il s'agit d'une matrice pour le rendu/simulation 3D, je recommande de ne pas allouer dynamiquement la mémoire de cette manière. Vous pouvez vous retrouver avec la mémoire se répandre partout, ce qui provoque des problèmes de mise en cache. Il conduit également à des bogues de mémoire potentiels.

template <typename T> 
class Matrix 
{ 
    public: 
     T m_Data[4][4]; 
}; 

ou si vous voulez quelque chose de non-4x4

template <typename T, unsigned int rows, unsigned int columns> 
class Matrix 
{ 
    public: 
     T m_Data[rows][columns]; 
}; 

puis allouer dynamiquement les objets Matrix.

+0

Ceci est hors-sujet, mais j'ai fait du travail en 3D et je peux me voir vouloir utiliser ma classe de matrice là, et je vois ce que vous voulez dire. des liens ou d'autres conseils? – jakev

1

Voilà comment je l'ai mis en œuvre ces opérateurs pour une matrice classe, cela est basé sur une classe Vector . Une fois que vous définissez certains opérateurs, tous les autres devraient être définis en termes d'opérateurs les plus simples:

Matrix::Matrix(const Matrix& rMatrix) : 
    _iRows(rMatrix._iRows), _iColumns(rMatrix._iColumns), _pVector(0) 
{ 
    _pVector = new Vector[_iRows]; 
    for (int i = 0; i < _iRows; i++) { _pVector[i] = rMatrix._pVector[i]; } 
} 

Matrix& Matrix::operator=(const Matrix& rMatrix) 
{ 
    if (this != &rMatrix) 
    { 
     if (0 != _pVector) { delete[] _pVector; pVector = 0; } 
     _iRows = rMatrix._iRows; 
     _iColumns = rMatrix._iColumns; 
     _pVector = new Vector[_iRows]; 
     for (int i = 0; i < _iRows; i++) { _pVector[i] = rMatrix._pVector[i]; } 
    } 
    return *this; 
} 
Matrix& Matrix::operator+=(const Matrix& rMatrix) 
{ 
    *this = *this + rMatrix; 
    return *this; 
} 

Matrix Matrix::operator+(const Matrix& rMatrix) const 
{ 
    Matrix matrix(_iRows, _iColumns); 
    ValidateSizes(rMatrix); 
    for (int i = 0; i < _iRows; i++) { matrix._pVector[i] = _pVector[i] + rMatrix._pVector[i]; } 
    return matrix; 
} 

Matrix operator+(const Matrix& rMatrix, double dNum) 
{ 
    Matrix matrix(rMatrix._iRows, rMatrix._iColumns); 
    matrix.ValidateSizes(rMatrix); 
    for (int i = 0; i < matrix._iRows; i++) { matrix._pVector[i] = dNum + rMatrix._pVector[i]; } 
    return matrix; 
} 

Matrix operator+(double dNum, const Matrix& rMatrix) 
{ 
    return operator+(rMatrix, dNum); 
} 

bool Matrix::ValidateSizes(const Matrix& rMatrix) const 
{ 
    if (_iRows != rMatrix._iRows) { /* THROW EXCEPTION */ } 
    if (_iColumns != rMatrix._iColumns) { /* THROW EXCEPTION */ } 
    return true; 
}