1. Most of us know how to use a vector or array template as a linear array. What should we do when we need a two-dimensional matrix, a three-dimensional array (or an n-dimensional array.
Since all problems in the basic situation of n-dimensional arrays can be illustrated by a two-dimensional matrix, the following discussion is limited to this, and is simply called a matrix.
If the matrix size is known during compilation, it can be easily implemented as an array. This is very simple. Here, we mainly focus on the fact that when the matrix size is calculated at runtime, we can easily use vector or vector to implement this complicated situation. In fact, if different rows must have different lengths, this is the only feasible method. However, in most cases, all rows should have the same length. In this case, using vector is an inefficient method: it needs to allocate memory multiple times, this is a relatively slow operation. An important reason for using C ++ is the pursuit of efficiency. Therefore, we try a different method, that is, to create a rectangular matrix by only one memory allocation.
Sample Code:
// Two-dimensional rectangular matrix template <typename T> class Matrix {public: typedef unsigned size_type; matrix (size_type num_rows, size_type num_cols): rows _ (num_rows), cols _ (num_cols ), data _ (num_rows * num_cols) {scpp_test_assert (num_rows> 0, "number of rows in a matrix must be positive"); scpp_test_assert (num_cols> 0, "Number of columns in a matrix must be positive");} matrix (size_type num_rows, size_type num_cols, const T & init_value): rows _ (num_rows), cols _ (num_cols ), data _ (num_rows * num_cols, init_value) {scpp_test_assert (num_rows> 0, "number of rows in a matrix must be positive"); scpp_test_assert (num_cols> 0, "Number of columns in a matrix must be positive");} size_type num_rows () const {return rows _;} size_type num_cols () const {return Cols _;} // access method: return the T & operator () (size_type row, size_type col) {return data _ [index (row, col)] specified by rows and columns;} const T & operator () (size_type row, size_type col) const {return data _ [index (row, col)];} PRIVATE: size_type rows, cols; STD :: vector <t> data _; size_type insex (size_type row, size_type col) const {scpp_test_assert (row <rows _, "Row" <row <"must be less than" <rows _); scpp_test_assert (COL <Cols _, "column" <Col <"must be less than" <Cols _); Return Cols _ * row + Col ;}};
First, there are two constructors in this class. The first constructor allows us to create a matrix with the specified number of rows and columns. The second constructor has an additional init_value parameter. Each element can be initialized to a specified value (for example, each element of a matrix <double> is set to 0.0 ). Note that the () operator is used for element access. This is because the [] operator of c ++ only accepts one parameter and cannot accept two or more parameters. Therefore, to access multi-dimensional arrays, we can use multiple [] (for example, my_matrix [I] [J]) or one () operator (for example, my_matrix (I, j )).
If we ask the [] operator to return a pointer of the T * type pointing to the 0th elements of line I, we can implement the first method. However, in this way, the column Index out-of-bounds issue cannot be diagnosed, which violates the original intention of capturing defects during runtime. Of course, we can create some template classes, including a smart reference pointing to a column, and return an instance of it using the first operator ([I, use the boundary check in the second operator ([J. To some extent, this is because of human habits. We don't see the value of adopting this complex design just to retain the syntax of my_matrix [I] [J]. Obviously, the () operators with multiple parameters seem more intuitive.
The check for index out-of-bounds is performed in the index (row, col) function. These two parameters indicate the number of rows and the number of columns respectively. If a running error occurs, an error processing function is called.
Finally, at the end of the sample code, a <operator of the matrix <t> template is provided to output the matrix:
cout<<"my matrix = \n"<<my_matrix<<endl;
However, the premise is that the matrix cannot be too large and the type T defines the <operator.
Conclusion: the rule to avoid "indexing out of bounds" is as follows:
- Do not use static or dynamically allocated arrays. You can use array or vector templates instead.
- Do not use the new and delete operators with square brackets to allocate memory to multiple elements in the Vector Template.
- Use SCPP: vector instead of STD: vector, use SCPP: array instead of static array, and enable security check.
- For multi-dimensional arrays, SCPP: matrix is used and elements are accessed through the () operator. An out-of-bounds index check is provided.