【问题标题】:C++ operator+ and operator+= overloadingC++ operator+ 和 operator+= 重载
【发布时间】:2010-12-07 22:45:46
【问题描述】:

我正在用 C++ 实现自己的矩阵类,以帮助我加深对语言的理解。我在某处读到,如果您有一个有效的 += 运算符,请在您的 + 运算符中使用它。这就是我所拥有的:

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

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

这里是 += 运算符重载:

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;
}

我可以使用 += 就好了(例如,a += b;不返回错误)。但是调用 + 运算符(例如,a = b + c;)会返回:

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

为了完整起见,这是我的析构函数:

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

我已经断断续续地使用 C++ 几年了,但有时仍然无法跟踪指针。我希望这是正常的... 任何帮助都会很棒。谢谢!

编辑:这是我的复制构造函数。它被设置为释放数据数组,但我删除了它。现在我遇到了分段错误。

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);
        }
    }

}

【问题讨论】:

  • 你的复制构造函数是什么样的?这可能是您的问题,因为该错误表明内存被释放了两次。
  • @Walt W:是的,我怀疑这是三巨头的问题。
  • @Fred:三大问题是什么?
  • 现在我们看到您有一个有效的,请参阅 Fritschy 的回答 :)
  • 不要被骗养成将 const 引用视为传递值的聪明方法的坏习惯……这样做时,您应该始终考虑生命周期和可能的别名。在这种情况下,您将返回对局部变量的引用,这是不行的。

标签: c++ operator-overloading


【解决方案1】:

operator+() 不应返回引用类型,因为它是保存操作结果的新(本地声明的)实例。

【讨论】:

  • +1:您正在返回对在堆栈卸载时立即销毁的对象(矩阵副本)的引用; C++ 引用与 Java / C# / etc 引用不同。
【解决方案2】:

这就是我为 Matrix 类 实现此类运算符的方式,它基于 Vector 类。一旦你定义了一些运算符,所有其他的都应该根据最简单的运算符来定义:

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;
}

【讨论】:

    【解决方案3】:

    如果这是一个用于 3D 渲染/模拟的矩阵,我建议不要像那样动态分配内存。您最终可能会导致内存散布在整个地方,这会导致缓存问题。它还会导致潜在的内存错误。

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

    或者如果你想要一些非 4x4 的东西

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

    然后动态分配Matrix对象。

    【讨论】:

    • 这是题外话,但我已经完成了一些 3d 工作,并且可以看到自己想在那里使用我的矩阵类,我明白你的意思。任何链接或其他建议?
    最近更新 更多