0

在 C++ 程序中,这里有两个运算符标题用作未显示的矩阵实现的 setter 和 getter。

double* Matrix::operator[](unsigned int row) const throw (MatrixException);
double* Matrix::operator[](unsigned int row) throw (MatrixException);

在不进一步了解上述运算符的实现的情况下,只需查看上述运算符是如何定义的,如果同时实现这两种方法,矩阵程序中的设计缺陷将是什么。

关于 [] 运算符如何工作的说明: 矩阵设置如下:

Matrix *a = new Matrix(1,2); //matrix with one row and two columns
a[0][0] = 3.0; 
a[0][1] = 2.3;

//to access a matrix value
double* b = a[0][1];
delete a;

编辑:您会在运算符定义中进行哪些更改以修复设计缺陷?

4

2 回答 2

0

第一个设计缺陷是使用异常规范,在C++11中已弃用。

第二个设计缺陷是您可以从行列中索引,并且类无法检查它。IE,

Matrix a( 1, 2 );
double b = a[0][4];

使用代理可以进行边界检查。

struct Matrix {
    struct Column {
        double operator[](unsigned int column);
    };

    Column operator[](unsigned int row);
};

最后,你的例子完全是假的。你声明a为一个指针,所以当你下标时,a[0][0]你实际上是先下标指针,然后是行。

于 2012-12-21T21:02:14.430 回答
0

有一些缺陷。

最明显的一个是通过手动内存管理不必要地使用动态内存。任何时候你看到delete你几乎都知道有什么不对劲,任何时候你看到new你都应该怀疑。

Matrix a(1, 2); // no new needed
a[0][0] = 3.0;
a[0][1] = 2.3;
double * b = a[0][1];
// no delete needed

这可以完全防止内存泄漏。它还避免了您包含的未实际索引数组的错误(您需要使用它(*a)[0][0]来获取第一个元素)。

其次,您应该返回对值的引用,而不是指针。

第三,您应该使用一个返回值并将两个索引作为参数的函数,而不是重载 anoperator[]以返回一个您必须再次取消引用的数组。http://www.parashift.com/c++-faq/matrix-subscript-op.html

这允许您检查边界,假设Matrix知道它自己的大小是多少(它必须存储两个整数数据成员)。

double const & Matrix::at(size_t const row, size_t const column) const {
    check_bounds(row, column);
    return implementation_detail();
}

具有明显的double &版本实现。就目前而言,您的const成员函数版本返回 adouble *而不是通过返回 a 来使const传递double const *(尽管仍然首选引用)。

另一个潜在的缺陷是像 a 这样的泛型类Matrix可能应该在类型上参数化:

template<typename T>
class Matrix {
public:
    typedef T value_type;
    ...
};

因此,您的示例实际上将使用 aMatrix<double>作为类型。

最后,我要对异常规范说不。它们往往会导致比修复更多的错误,这就是它们在 C++11 中被弃用的原因。

于 2012-12-21T21:03:19.630 回答