|
||||
|
Section 16:
|
[16.19] What's another way to build a Matrix template?
Use the standard vector template, and make a vector of vector. The following uses a std::vector<std::vector<T> > (note the space between the two > symbols). #include <vector> template<typename T> // See section on templates for more class Matrix { public: Matrix(unsigned nrows, unsigned ncols); // Throws a BadSize object if either size is zero class BadSize { }; // No need for any of The Big Three! // Access methods to get the (i,j) element: T& operator() (unsigned i, unsigned j); ← subscript operators often come in pairs T const& operator() (unsigned i, unsigned j) const; ← subscript operators often come in pairs // These throw a BoundsViolation object if i or j is too big class BoundsViolation { }; unsigned nrows() const; // #rows in this matrix unsigned ncols() const; // #columns in this matrix private: std::vector<std::vector<T> > data_; }; template<typename T> inline unsigned Matrix<T>::nrows() const { return data_.size(); } template<typename T> inline unsigned Matrix<T>::ncols() const { return data_[0].size(); } template<typename T> inline T& Matrix<T>::operator() (unsigned row, unsigned col) { if (row >= nrows() || col >= ncols()) throw BoundsViolation(); return data_[row][col]; } template<typename T> inline T const& Matrix<T>::operator() (unsigned row, unsigned col) const { if (row >= nrows() || col >= ncols()) throw BoundsViolation(); return data_[row][col]; } template<typename T> Matrix<T>::Matrix(unsigned nrows, unsigned ncols) : data_ (nrows) { if (nrows == 0 || ncols == 0) throw BadSize(); for (unsigned i = 0; i < nrows; ++i) data_[i].resize(ncols); }Note how much simpler this is than the previous: there is no explicit new in the constructor, and there is no need for any of The Big Three (destructor, copy constructor or assignment operator). Simply put, your code is a lot less likely to have memory leaks if you use std::vector than if you use explicit new T[n] and delete[] p. Note also that std::vector doesn't force you to allocate numerous chunks of memory. If you prefer to allocate only one chunk of memory for the entire matrix, as was done in the previous, just change the type of data_ to std::vector<T> and add member variables nrows_ and ncols_. You'll figure out the rest: initialize data_ using data_(nrows * ncols), change operator()() to return data_[row*ncols_ + col];, etc. |
|||