避免"索引越界"错误的规则如下(针对C++):
- 不要使用静态或动态分配的数组,改用array或vector模板
- 不要使用带方括号的new和delete操作符,让vector模板为多个元素分配内存
- 使用scpp::vector代替std::vector,使用scpp::array代替静态数组,并打开安全检查(自动在使用下标访问提供了索引边界检查)
C++中创建类型T的对象的数组方式如下:
- #define N 10
- T static_arr[N]; //数组长度在编译时已知
-
- int n=20;
- T* dynamic_arr=new T[n]; //数组长度在运行时计算
-
- std::vector<T> vector_arr; //数组长度在运行时进行修改
-
1. 动态数组
采用的办法是继承std::vector<T>,并重载<< 、[]运算符,提供一个能够捕捉越界访问错误的实现。
实现代码和测试如下:
- //scpp_vector.h
- #ifndef _SCPP_VECTOR_
- #define _SCPP_VECTOR_
-
- #include <vector>
- #include "scpp_assert.h"
-
- namespace scpp {
-
- //wrapper around std::vector,在[]提供了临时的安全检查:重载[] <<运算符
- template<typename T>
- class vector : public std::vector<T> {
- public:
- typedef unsigned size_type;
-
- //常用的构造函数 commonly use cons
- 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) {
-
- }
-
- //Note : we don't provide a copy-cons and assignment operator ?
-
- //使用scpp::vector提供更安全的下标访问实现,它可以捕捉越界访问错误
- T& operator[] (size_type index) {
- SCPP_ASSERT( index < std::vector<T>::size() ,
- "Index " << index << " must be less than " << std::vector<T>::size());
- return std::vector<T>::operator[](index);
- }
-
- //? difference
- const T& operator[] (size_type index) const {
- SCPP_ASSERT( index < std::vector<T>::size() ,
- "Index " << index << " must be less than " << std::vector<T>::size());
- return std::vector<T>::operator[](index);
- }
-
- //允许此函数访问这个类的私有数据
- //friend std::ostream& operator<< (std::ostream& os,const ) ?
- };
- } //namespace
-
- template<typename T>
- inline std::ostream& operator<< (std::ostream& os,const scpp::vector<T>& v) {
- for(unsigned i=0 ;i<v.size();i++) {
- os << v[i];
- if( i+1 < v.size()) os << " ";
- }
- return os;
- }
-
-
- #endif
-
- //test_vector.cpp
- #include "scpp_vector.h"
- #include <iostream>
-
- using namespace std;
- int main() {
- //usage-创建一个具有指定数量的vector:scpp::vector<int> v(n); 把n个vector元素都初始化为一个值:scpp::vector<int> v(n,val)
- //方法3:scpp::vector<int> v; v.reserve(n),表示开始的vector是空的,对应的size()为0,
- //并且开始添加元素时,在长度达到n之前,不会出现导致速度降低的容量增长现象
- scpp::vector<int> vec;
- for(int i=0;i< 3;i++){
- vec.push_back(4*i);
- }
- cout << "The vector is : "<< vec <<endl;
-
- for(int i=0;i <= vec.size();i++) {
- cout << "Value of vector at index " << i << " is " << vec[i] << endl;
- }
- return 0;
- }
我们直接使用scpp::vector而尽量不与std::vector交叉使用。
2.静态数组
静态数组是在栈上分配内存,而vector模板是在构造函数中用new操作符分配内存的,速度相对慢些,为保证运行时效率,建议使用array模板(同样也是栈内存),实现代码和测试如下:
- //scpp_array.h
- #ifndef _SCPP_ARRAY_H_
- #define _SCPP_ARRAY_H_
-
- #include "scpp_assert.h"
-
- namespace scpp {
-
- //wrapper around std::vector,在[]提供了临时的安全检查
- //fixed-size array
- template<typename T,unsigned int N>
- class array {
- public:
- typedef unsigned int size_type;
-
- //常用的构造函数 commonly use cons
- array() {}
- explicit array(const T& val) {
- for(unsigned int i=0;i < N;i++) {
- m_data[i]=val;
- }
- }
-
- size_type size() const {
- return N;
- } //must use const if we use the size()
-
- //Note : we don't provide a copy-cons and assignment operator ?
-
- T& operator[] (size_type index) {
- SCPP_ASSERT( index < N,
- "Index " << index << " must be less than " << N);
- return m_data[index];
- }
-
- //? difference
- const T& operator[] (size_type index) const {
- SCPP_ASSERT( index < N ,
- "Index " << index << " must be less than " << N);
- return m_data[index];
- }
-
- //模拟迭代器的begin和end方法
- //访问方法accessors
- T* begin() {
- return &m_data[0];
- }
-
- const T* begin() const {
- return &m_data[0];
- }
-
- //返回越过数组尾部的迭代器
- T* end() {
- return &m_data[N];
- }
-
- const T* end() const {
- return &m_data[N];
- }
- private:
- T m_data[N];
- };
- } //namespace scpp
-
- template<typename T,unsigned int N>
- inline std::ostream& operator<< (std::ostream& os,const scpp::array<T,N>& v) {
- for(unsigned int i=0 ;i< N;i++) {
- os << v[i];
- if( i+1 < v.size()) os << " ";
- }
- return os;
- }
- #endif
-
- //test_array.cpp
- #include "scpp_array.h"
- #include <iostream>
- #include <algorithm> //sort algorithm
- using namespace std;
- int main() {
- //use vector/array class instead of static array or dynamic array
- scpp::array<int,5u > arr(0);
- arr[0]=7;
- arr[1]=2;
- arr[2]=3;
- arr[3]=9;
- arr[4]=0;
-
- cout << "Array before sort : " << arr << endl;
- sort(arr.begin(),arr.end());
- cout << "Array after sort : "<< arr << endl;
-
- arr[5]=8;
- return 0;
- }
到此这篇关于C++索引越界的解决方法的文章就介绍到这了,更多相关C++索引越界内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!