0

复制构造函数和赋值运算符有问题。编写了乘法矩阵的代码:

Matrix& Matrix::operator * (const Matrix &second) const
{
    // Create result matrix
    Matrix result(Rows(), second.Columns());

    // Multiply matricies
    for (unsigned i = 0; i < Rows(); i++)
    {
         for (unsigned j = 0; j < second.Columns(); j++)
         {
             result[i][j] = 0.0;

             for (unsigned k = 0; k < Columns(); k++)
             {
                 result[i][j] += m_matrix[i][k] * second[k][j];
             }
         }
    }

    return result;
}

在主代码中,我调用操作员:

Matrix C = A * B;

然而代码在赋值之前破坏了结果变量,如何正确编写这样的代码来返回结果矩阵?复制构造函数是:

Matrix::Matrix(const Matrix& matrix)
{
    AllocateMatrixArray(matrix.Rows(), matrix.Columns());
    CopyMatrixData(matrix);
}

赋值运算符是:

Matrix& Matrix::operator = (const Matrix& other)
{
    AllocateMatrixArray(other.Rows(), other.Columns());
    CopyMatrixData(other);
    return *this;
}

但是我看到编译器不使用它 - 复制构造函数就足够了。

4

3 回答 3

1

您不应该返回对局部变量的引用。按照惯例opertor*(我的意思当然是两个参数版本)返回结果的副本。同样适用于其他操作,如operator+,operator-等等。引用由这些运算符的修改版本返回,例如operator *=,operator +=等等。

于 2013-01-25T15:06:44.170 回答
1

您的代码返回对局部变量的引用,该变量将在函数作用域的末尾被销毁。不要这样做:

Matrix Matrix::operator * (const Matrix &second) const {
     // same as above
}

请注意,返回值现在是 aMatrix而不是 a Matrix&

于 2013-01-25T15:07:59.870 回答
1

如果你想写像 C = A*B 这样的表达式,所有的 CA 和 B 都必须是“值”。

所以返回值operator*must bematrix和 not matrix&,特别是如果&引用局部变量(如result),则将在}(因此在执行 = 之前)销毁。

也就是说,还有一些问题:

  • 该示例Matrix C = A*B不是赋值:赋值发生在已经存在的对象的值发生更改时。但是Matrix C是根据上下文创建的:其实这里调用的是Matrix构造函数(本例中是拷贝构造函数)

  • 可能存在内存泄漏:虽然我看不到如何处理矩阵数据,但您operator= 似乎分配了新空间,然后将数据复制到其中。但是包含旧数据的空间会发生什么?它是否仍然被遗忘?是由智能指针自动释放吗?

  • Similarly, just like = should dismiss the old data, also the class itself should dismiss its own data on destruction, hence a destructor should also be implemented. Otherwise every time a Matrix is dismissed (like the local result), its data will stay around.

于 2013-01-25T15:51:02.747 回答