C++索引越界的解决方法
作者:Welcom to LyAsano’s blog! 发布时间:2023-07-21 21:53:17
标签:C++,索引,越界
避免"索引越界"错误的规则如下(针对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;
}
来源:https://www.cnblogs.com/AsanoLy/p/15093442.html


猜你喜欢
- 学习在于记录,把自己不懂得容易忘记得记录下,才是最好得选择。废话不多说,想要在Android开发中嵌入c/c++代码,直接开始如下步骤1、创
- 首先在新建了一个web服务文件。public SqlWhhWebService1() &nbs
- 本文实例讲述了C#计算字符串哈希值(MD5、SHA)的方法。分享给大家供大家参考。具体如下:一、关于本文本文中是一个类库,包括下面几个函数:
- 今天使用mybatis-plus自动填充插入和更新时间有8小时时差后来发现只需要修改一下mybaits连接的url即可原先我是用的datas
- 前言:根据ThreadPoolExecutor的构造方法,JDK提供了很多工厂方法来创建各种用途的线程池.1 newFixedThreadP
- 本文实例讲述了DevExpress设置饼状图的Lable位置的方法。分享给大家供大家参考。具体实现方法如下:关键代码如下:/// <s
- 本文实例为大家分享了Android九宫格图片展示的具体代码,供大家参考,具体内容如下using System;using Microsoft
- 背景今天我们来谈一下我们自定义的一组WPF控件Form和FormItem,然后看一下如何自定义一组完整地组合WPF控件,在我们很多界面显示的
- 零、关于HibernateHibernate是冬眠的意思,它是指动物的冬眠,但是本文讨论的Hibernate却与冬眠毫无关系,而是接下来要讨
- 一、实现了Aware的接口Spring中有很多继承于aware中的接口,这些接口到底是做什么用到的,下面我们就一起来看看吧。Aware 接口
- 最近回顾了一下java继承中的问题,下面贴代码:public class Base {protected String temp = &qu
- 最近接触到INI配置文件的读写,虽然很久以前微软就推荐使用注册表来代替INI配置文件,现在在Visual Stud
- 一、导入相关jar包,pom依赖如下: <dependency> <groupId>org
- 近日在工作中需要根据设备的HardwareID来获取设备的驱动程序信息,比如驱动程序版本等。经过摸索,得到了两种不同的解决办法,两种办法各有
- 反射方式获取JPA Entity属性和值在记录日志或者调试的时候,往往需要输出数据库查询或者写入的值,或者在接 * 互的时候,可能需要将实体转
- 记录web项目部署到阿里云服务器步骤(使用 web项目、阿里云服务器、Xftp、Xshell),敬请参考和指正1.将要部署的项目打包成WAR
- 一、配置逆向generatoe.xml<?xml version="1.0" encoding="UTF
- 本文实例为大家分享了C#类的多态性,供大家参考,具体内容如下第一种:编译时的多态性,直接这样说不知道说啥?程序执行过程主要分为三步:编译,链
- 前言本文基于itext7实现pdf加水印和合并的操作。实际上在我们实际项目应用中,对于pdf的操作也是比较常见的,我上一个项目中就有将结果转
- 想要php版的朋友可以到这里下载测试 https://www.jb51.net/codes/83179.htmlimport java.io