C++数组超界错误

在正常情况下,为数组元素赋值时,数组array的索引应当在 [0, (sizeof(array)/sizeof(array[0]))-1]。但当数组索引为负数时,例如

double array[4];
array[-2] = 1.5; 

此时会发生什么呢?
示例取自C++ Primer Plus 第六版(Stephen Prata)第四章复合类型 4.10数组的替代品 程序清单4.2 choice.cpp

#include<iostream>
#include<vector>
#include<array>
using namespace std;

int main()
{
	double a1[4] = {1.2, 2.4, 3.6, 4.8};

	vector<double> a2(4);
	a2[0] = 1.0/3.0;
	a2[1] = 1.0/5.0;
	a2[2] = 1.0/7.0;
	a2[3] = 1.0/9.0;

	array<double, 4> a3 = {3.14, 2.72, 1.62, 1.41};
	array<double, 4> a4;
	a4 = a3;

	cout << "a1[2]: " << a1[2] << " at " << &a1[2] << endl;
	cout << "a2[2]: " << a2[2] << " at " << &a2[2] << endl;
	cout << "a3[2]: " << a3[2] << " at " << &a3[2] << endl;
	cout << "a4[2]: " << a4[2] << " at " << &a4[2] << endl;
	
	a1[-2] = 20.2;
	cout << "a1[-2]: " << a1[-2] << " at " << &a1[-2] << endl;
	cout << "a3[2]: " << a3[2] << " at " << &a3[2] << endl;
	cout << "a4[2]: " << a4[2] << " at " << &a4[2] << endl;

	system("pause");
	return 0;
}

程序结果为:

a1[2]: 3.6 at 0x28cce8
a2[2]: 0.142857 at 0xca0328
a3[2]: 1.62 at 0x28ccc8
a4[2]: 1.62 at 0x28cca8
a1[-2]: 20.2 at 0x28ccc8
a3[2]: 20.2 at 0x28ccc8
a4[2]: 1.62 at 0x28cca8

不同情况下,程序运行结果并不同。书中给出的结果中,a3[2] 的值也被更改为 20.2。而我的运行结果中 a3[2] 依然为 1.62。为什么会出现此种情况?

程序重点介绍数组、vector对象、array对象的相似和不同之处,但也介绍了一种数组超界错误,即

	a1[-2] = 20.2;

该语句将被转化为:

	*(a1-2) = 20.2;

其含义为:找到 a1 指向的地方,向前移动两个double元素,并将20.2存储到目的地,即将信息存储到数组的外面。

可以发现,a1[2] 存储地址为 0x28cce8,double类型占8 bytes,可得 a1[-2] 的存储地址为 0x28ccc8,正好为a3[2] 的存储地址,因此a3[2] 的值被覆盖为20.2。也可以说这是因为,a1[-2]a3[2] 指向同一块内存。

而如果a1[-2] 并未与程序中其他元素的地址重合,则不会出现其他元素一起被修改的意外情况。

书中给出了一种避免该情况出现的选择,使用成员函数 at()

a2.at(1) = 2.3; // assign 2.3 to a2[1]

中括号表示法和成员函数 at() 的差别在于,使用 at() 时,将在运行期间捕获非法索引,而程序默认将中断。这种额外检查的代价是运行时间更长,这就是 C++ 允许使用任何一种表示法的原因所在。使用 vector 和 array 等类能够降低意外超界错误的概率,将在后面进一步讨论。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值