三、索引越界 1、動態數組可以使用new,也可以用vector來動態創建 但是當下標的索引超過size的時候,new出來的數組對其進行更改的時候會有不確定的錯誤產生;vector提供了一個at(index)的函數,他通過拋出一個out_of_range異常執行邊界檢測 測試代碼(vs2012+win7環境): [cpp] #include "stdafx.h" #include "scpp_assert.h" #include "iostream" #include "vector" #define SIZE 10 int _tmain(int argc, _TCHAR* argv[]) { char *str = new char[SIZE]; str[SIZE + 1] = 'x'; std::vector<char> arrayStr; arrayStr.resize(SIZE); arrayStr[11] = 'x'; return 0; } 他的問題在於如果我們想執行這種安全檢查,必須在訪問數組元素的每個地方都嚴格地使用at()函數。顯然這種做法會降低代碼的效率,因此在完成了測試之後,我們可能想要速度更快的[]操作符在每處對他繼續擰替換。但是,這樣的替換對代碼進行大量的修改。因此可以使用下面的方法(以解決不必使用at函數): [cpp] #ifndef __SCPP_VECTOR_H__ #define __SCPP_VECTOR_H__ #include "scpp_assert.h" #include "vector" namespace scpp { template <typename T> class vector : public std::vector<T> { public: typedef unsigned size_type; public: explicit vector(size_type n = 0) : std::vector<T>(n){ } vector(size_type n, const T& value) : std::vector<T>(n, value){ } template <class InputIterator> vector(InputIterator first, InputIterator last) : std::vector<T>(first, last){ } T &operator[] (size_type index) { SCPP_TEST_ASSERT(index < std::vector<T>::size(), "Index " << index << " must be less than " << std::vector<T>::size()); return std::vector<T>::operator [](index); } const T &operator[] (size_type index) const { SCPP_TEST_ASSERT(index < std::vector<T>::size(), "Index " << index << " must be less than " << std::vector<T>::size()); return std::vector<T>::operator [](index); } }; }; // namespace scpp template <typename T> inline std::ostream &operator << (std::ostream &os, const scpp::vector<T>& v) { for (unsigned index = 0; index < v.size(); ++index) { os << v[index]; if (index + 1 < v.size()) { os << " "; } } return os; } #endif 測試代碼(vs2012+win7環境): [cpp] #include "stdafx.h" #include "scpp_assert.h" #include "iostream" #include "scpp_vector.h" #define SIZE 10 int _tmain(int argc, _TCHAR* argv[]) { scpp::vector<char> str(SIZE, 'z'); std::cout << str << std::endl; str[20] = 'x'; return 0; } 在stdafx.h中打開調試開關: [cpp] #pragma once #include "targetver.h" #include <stdio.h> #include <tchar.h> // TODO: 在此處引用程序需要的其他頭文件 /*#define SCPP_THROW_EXCEPTION_ON_BUG*/ #define SCPP_TEST_ASSERT_ON 2、靜態數組: scpp::vector vect(SIZE)他的效果與靜態數組完全相同,但問題在於效率。靜態數組是在堆棧上分配內存,而vector模板輸在構造函數中使用new操作符分配的,速度比較慢,所以這裡有array模板: scpp_array.h: [cpp] #ifndef __SCPP_ARRAY_H__ #define __SCPP_ARRAY_H__ #include "scpp_assert.h" namespace scpp { template <typename T, unsigned N> class array { public: typedef unsigned size_type; public: array(){ } explicit array(const T& initialValue) { for (size_type index = 0; index < N; ++index) { data_[index] = initialValue; } } size_type size() const { return N; } T& operator[](size_type index) { SCPP_TEST_ASSERT(index < N, "Index " << index << " must be less than " << N); return data_[index]; } const T& operator[](size_type index) const { SCPP_TEST_ASSERT(index < N, "Index " << index << " must be less than " << N); return data_[index]; } T* begin() { return &data_[0]; } const T* begin() const { return &data_[0]; } T* end() { return &data_[N]; } const T* end() const { return &data_[N]; } private: T data_[N]; }; } template <typename T, unsigned N> inline std::ostream &operator << (std::ostream &os, const scpp::array<T, N>& v) { for (unsigned index = 0; index < v.size(); ++index) { os << v[index]; if (index + 1 < v.size()) { os << " "; } } return os; } #endif // __SCPP_ARRAY_H__ 測試代碼(vs2012+win7環境): [cpp] #include "stdafx.h" #include "scpp_assert.h" #include "iostream" #include "scpp_vector.h" #include "scpp_array.h" #include "algorithm" #define SIZE 10 int _tmain(int argc, _TCHAR* argv[]) { scpp::array<int, SIZE> str(1); str[0] = 7; str[1] = 2; str[2] = 8; str[3] = 4; std::cout << str << std::endl; std::sort(str.begin(), str.end()); std::cout << str << std::endl; return 0; } 這個數組的行為和C的靜態數組完全一樣。但是,在編譯時激活了表示安全檢查的SCPP_TEST_ASSERT_ON宏時,他會提供索引邊界檢查。提供了begin和end方法,所以可以使用algorithm的一些算法 3、多維數組 其實多維數組也就是矩陣,如果矩陣的大小在編譯時時已知的,可以很方便地把它實現為數組的數組。因此將注意力集中在當矩陣的大小是在運行時計算產生的這種情況。內部可以用一個vector來存儲,返回的時候只需要加上index就行 scpp_matrix.h: [cpp] #ifndef __SCCP_MATRIX_H__ #define __SCCP_MATRIX_H__ #include "ostream" #include "vector" #include "scpp_assert.h" namespace scpp { template <typename T> class matrix { public: typedef unsigned size_type; public: matrix(size_type numRows, size_type numCols) :rows_(numRows), cols_(numCols), data_(numCols * numRows) { SCPP_TEST_ASSERT(numRows > 0, "Number of rows in a matrix must be positive"); SCPP_TEST_ASSERT(numCols > 0, "Number of cols in a matrix must be positive"); } matrix(size_type numRows, size_type numCols, const T& initValue) :rows_(numRows), cols_(numCols), data_(numCols * numRows) { SCPP_TEST_ASSERT(numRows > 0, "Number of rows in a matrix must be positive"); SCPP_TEST_ASSERT(numCols > 0, "Number of cols in a matrix must be positive"); } size_type numRows() const { return rows_; } size_type numCols() const { return cols_; } T& operator() (size_type row, size_type col) { return data_[ index(row, col) ]; } const T& operator() (size_type row, size_type col) const { return data_[ index(row, col) ]; } private: size_type index(size_type row, size_type col) const { SCPP_TEST_ASSERT(row < rows_, "Row" << row << " must be less than " << rows_); SCPP_TEST_ASSERT(col < cols_, "Col" << col << " must be less than " << cols_); return cols_ * row + col; } private: size_type rows_; size_type cols_; vector<T> data_; }; } template <typename T> inline std::ostream &operator << (std::ostream &os, const scpp::matrix<T>& m) { for (unsigned rowIndex = 0; rowIndex < m.numRows(); ++rowIndex) { for (unsigned colIndex = 0; colIndex < m.numCols(); ++colIndex) { os << m(rowIndex, colIndex); if (colIndex < m.numCols()) { os << "\t"; } } } return os; } #endif 測試代碼(vs2012+win7環境): [cpp] #include "stdafx.h" #include "scpp_assert.h" #include "iostream" #include "scpp_vector.h" #include "scpp_array.h" #include "scpp_matrix.h" #include "algorithm" #define SIZE 10 int _tmain(int argc, _TCHAR* argv[]) { scpp::matrix<int> scppMatrix(2, 2); scppMatrix(0, 0) = 1; scppMatrix(0, 1) = 2; scppMatrix(1, 0) = 3; scppMatrix(1, 1) = 4; scppMatrix(6, 6) = 4; std::cout << scppMatrix << std::endl; return 0; }