2012-12-21 41 views
0

在C++程序中,这里有两个运算符标题用作未示出的矩阵实现的setter和getters。在矩阵实现的[]运算符中发现设计缺陷

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; 

编辑:你会在运营商定义来解决设计上的缺陷变化?

+1

对于初学者,他们应该返回引用,而不是指针。此外,异常规范(函数旁边的'throw')已被弃用。 –

+2

像这样的抛出规范是混淆,误导和从C++ 11中删除(不推荐)。好消除 – Zeks

回答

0

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

第二个设计缺陷是,您可以索引出行列,并且没有办法让班级检查它。即,

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]时,您实际上是先对指针进行下标,然后再对该行进行下标。

+0

你将如何修改运算符定义来检查边界? – user1133324

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 

这可以完全防止内存泄漏。它也避免了你包含的实际上没有对数组索引的bug(你需要使用(*a)[0][0]来获得第一个元素)。

其次,您应该返回对该值的引用,而不是指针。第三,您应该返回一个函数,该函数返回值并将两个索引作为参数,而不是重载一个operator[]以返回一个数组,然后您必须再次解除引用。 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成员函数版本返回double *,而不是通过返回double const *(尽管仍然推荐引用)来使const传递。

另一个潜在的缺陷是,像Matrix泛型类的也许应该是参数的类型:

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

你的榜样,因此,实际上将使用Matrix<double>作为类型。

最后,我会拒绝异常规范。它们往往会导致比修复更多的bug,这就是为什么它们在C++ 11中被弃用的原因。