经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
C++索引越界的解决方法
来源:jb51  时间:2021/8/4 9:10:24  对本文有异议

避免"索引越界"错误的规则如下(针对C++):

  • 不要使用静态或动态分配的数组,改用array或vector模板
  • 不要使用带方括号的new和delete操作符,让vector模板为多个元素分配内存
  • 使用scpp::vector代替std::vector,使用scpp::array代替静态数组,并打开安全检查(自动在使用下标访问提供了索引边界检查)

C++中创建类型T的对象的数组方式如下:

  1. #define N 10
  2. T static_arr[N]; //数组长度在编译时已知
  3.  
  4. int n=20;
  5. T* dynamic_arr=new T[n]; //数组长度在运行时计算
  6.  
  7. std::vector<T> vector_arr; //数组长度在运行时进行修改
  8.  

1. 动态数组

  采用的办法是继承std::vector<T>,并重载<< 、[]运算符,提供一个能够捕捉越界访问错误的实现。

  实现代码和测试如下:

  1. //scpp_vector.h
  2. #ifndef _SCPP_VECTOR_
  3. #define _SCPP_VECTOR_
  4.  
  5. #include <vector>
  6. #include "scpp_assert.h"
  7.  
  8. namespace scpp {
  9.  
  10. //wrapper around std::vector,在[]提供了临时的安全检查:重载[] <<运算符
  11. template<typename T>
  12. class vector : public std::vector<T> {
  13. public:
  14. typedef unsigned size_type;
  15.  
  16. //常用的构造函数 commonly use cons
  17. explicit vector(size_type n=0) : std::vector<T>(n) {
  18.  
  19. }
  20. vector(size_type n,const T& value) : std::vector<T>(n,value) {
  21.  
  22. }
  23.  
  24. template <class InputIterator> vector(InputIterator first,InputIterator last)
  25. : std::vector<T>(first,last) {
  26.  
  27. }
  28. //Note : we don't provide a copy-cons and assignment operator ?
  29.  
  30. //使用scpp::vector提供更安全的下标访问实现,它可以捕捉越界访问错误
  31. T& operator[] (size_type index) {
  32. SCPP_ASSERT( index < std::vector<T>::size() ,
  33. "Index " << index << " must be less than " << std::vector<T>::size());
  34. return std::vector<T>::operator[](index);
  35. }
  36.  
  37. //? difference
  38. const T& operator[] (size_type index) const {
  39. SCPP_ASSERT( index < std::vector<T>::size() ,
  40. "Index " << index << " must be less than " << std::vector<T>::size());
  41. return std::vector<T>::operator[](index);
  42. }
  43.  
  44. //允许此函数访问这个类的私有数据
  45. //friend std::ostream& operator<< (std::ostream& os,const ) ?
  46. };
  47. } //namespace
  48.  
  49. template<typename T>
  50. inline std::ostream& operator<< (std::ostream& os,const scpp::vector<T>& v) {
  51. for(unsigned i=0 ;i<v.size();i++) {
  52. os << v[i];
  53. if( i+1 < v.size()) os << " ";
  54. }
  55. return os;
  56. }
  57.  
  58.  
  59. #endif
  60.  
  61. //test_vector.cpp
  62. #include "scpp_vector.h"
  63. #include <iostream>
  64.  
  65. using namespace std;
  66. int main() {
  67. //usage-创建一个具有指定数量的vector:scpp::vector<int> v(n); 把n个vector元素都初始化为一个值:scpp::vector<int> v(n,val)
  68. //方法3:scpp::vector<int> v; v.reserve(n),表示开始的vector是空的,对应的size()为0,
  69. //并且开始添加元素时,在长度达到n之前,不会出现导致速度降低的容量增长现象
  70. scpp::vector<int> vec;
  71. for(int i=0;i< 3;i++){
  72. vec.push_back(4*i);
  73. }
  74. cout << "The vector is : "<< vec <<endl;
  75.  
  76. for(int i=0;i <= vec.size();i++) {
  77. cout << "Value of vector at index " << i << " is " << vec[i] << endl;
  78. }
  79. return 0;
  80. }

  我们直接使用scpp::vector而尽量不与std::vector交叉使用。

2.静态数组

  静态数组是在栈上分配内存,而vector模板是在构造函数中用new操作符分配内存的,速度相对慢些,为保证运行时效率,建议使用array模板(同样也是栈内存),实现代码和测试如下:

  1. //scpp_array.h
  2. #ifndef _SCPP_ARRAY_H_
  3. #define _SCPP_ARRAY_H_
  4.  
  5. #include "scpp_assert.h"
  6.  
  7. namespace scpp {
  8.  
  9. //wrapper around std::vector,在[]提供了临时的安全检查
  10. //fixed-size array
  11. template<typename T,unsigned int N>
  12. class array {
  13. public:
  14. typedef unsigned int size_type;
  15.  
  16. //常用的构造函数 commonly use cons
  17. array() {}
  18. explicit array(const T& val) {
  19. for(unsigned int i=0;i < N;i++) {
  20. m_data[i]=val;
  21. }
  22. }
  23. size_type size() const {
  24. return N;
  25. } //must use const if we use the size()
  26. //Note : we don't provide a copy-cons and assignment operator ?
  27.  
  28. T& operator[] (size_type index) {
  29. SCPP_ASSERT( index < N,
  30. "Index " << index << " must be less than " << N);
  31. return m_data[index];
  32. }
  33.  
  34. //? difference
  35. const T& operator[] (size_type index) const {
  36. SCPP_ASSERT( index < N ,
  37. "Index " << index << " must be less than " << N);
  38. return m_data[index];
  39. }
  40.  
  41. //模拟迭代器的begin和end方法
  42. //访问方法accessors
  43. T* begin() {
  44. return &m_data[0];
  45. }
  46.  
  47. const T* begin() const {
  48. return &m_data[0];
  49. }
  50.  
  51. //返回越过数组尾部的迭代器
  52. T* end() {
  53. return &m_data[N];
  54. }
  55.  
  56. const T* end() const {
  57. return &m_data[N];
  58. }
  59. private:
  60. T m_data[N];
  61. };
  62. } //namespace scpp
  63.  
  64. template<typename T,unsigned int N>
  65. inline std::ostream& operator<< (std::ostream& os,const scpp::array<T,N>& v) {
  66. for(unsigned int i=0 ;i< N;i++) {
  67. os << v[i];
  68. if( i+1 < v.size()) os << " ";
  69. }
  70. return os;
  71. }
  72. #endif
  73.  
  74. //test_array.cpp
  75. #include "scpp_array.h"
  76. #include <iostream>
  77. #include <algorithm> //sort algorithm
  78. using namespace std;
  79. int main() {
  80. //use vector/array class instead of static array or dynamic array
  81. scpp::array<int,5u > arr(0);
  82. arr[0]=7;
  83. arr[1]=2;
  84. arr[2]=3;
  85. arr[3]=9;
  86. arr[4]=0;
  87.  
  88. cout << "Array before sort : " << arr << endl;
  89. sort(arr.begin(),arr.end());
  90. cout << "Array after sort : "<< arr << endl;
  91.  
  92. arr[5]=8;
  93. return 0;
  94. }

到此这篇关于C++索引越界的解决方法的文章就介绍到这了,更多相关C++索引越界内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号