关于 std::vector 的下标越界检查

当要获取 std::vector 的第 n 个元素,下面几种方式都可以:

std::vector<int> vec;
size_t n = 1;
int & i = vec[n];
int & j = *(vec.begin() + n);
int & k = vec.at(n);

但是如果 n 超过了 vector 的下标范围,在几种方式的结果就有区别了。

在 linux 平台只有 at(n) 会抛出 std::out_of_range 异常,而其他两个都不会。

 查看标准模板库代码,可以看到:

      // element access
      /**
       *  @brief  Subscript access to the data contained in the %vector.
       *  @param n The index of the element for which data should be
       *  accessed.
       *  @return  Read/write reference to data.
       *
       *  This operator allows for easy, array-style, data access.
       *  Note that data access with this operator is unchecked and
       *  out_of_range lookups are not defined. (For checked lookups
       *  see at().)
       */
      reference
      operator[](size_type __n)
      { return *(this->_M_impl._M_start + __n); }

有说明:通过 operator[] 获取数组元素,不会检查下标有效性,需要检查的时候使用 at 接口

在 windows 平台 VS 环境下,都会抛出异常,VC 下的标准库是这样现实的:

	reference operator[](size_type _Pos)
		{	// subscript mutable sequence

 #if _HAS_ITERATOR_DEBUGGING
		if (size() <= _Pos)
			{
			_DEBUG_ERROR("vector subscript out of range");
			_SCL_SECURE_OUT_OF_RANGE;
			}
 #endif /* _HAS_ITERATOR_DEBUGGING */
		_SCL_SECURE_VALIDATE_RANGE(_Pos < size());

		return (*(_Myfirst + _Pos));
		}

在 Debug 配置下, _HAS_ITERATOR_DEBUGGING 默认定义为 1,但是即使强制定义为 0,也有异常,因为还有一个 _SCL_SECURE_VALIDATE_RANGE 检查。所以即使在 Release 配置下,下标检查也是存在的。

如果把上面的代码中的“引用”符号去掉,像这样:

std::vector<int> vec;
size_t n = 1;
int i = vec[n];
int j = *(vec.begin() + n);
int k = vec.at(n);

那么 at(n) 仍然会抛出 std::out_of_range 异常,其他两个会出现什么情况呢,也许是内存访问异常,也许是其他诡异的错误。

在 vec 非空的情况下,即使下标越界,也有可能对应的内存是可读写的,至于读到的是什么内容,或者写到什么地方,就是随机事件了。

所以尽量用 at 接口,让错误尽早暴露出来。

 

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
std::array和std::vector是C++中两种常见的容器,它们都可以存储一组数据,但在使用上有一些不同。 1. 大小不同 std::array是一个静态数组,大小在编译时就被确定了,不能动态扩展。而std::vector是一个动态数组,大小可以在运行时根据需要动态扩展。 2. 内存分配不同 std::array在栈上分配内存,而std::vector在堆上分配内存。因此,std::array的内存管理更加简单和高效,但是其大小受到栈大小的限制,当数组过大时容易导致栈溢出;std::vector的内存管理相对复杂,但是其大小不受限制。 3. 初始化方式不同 std::array可以通过初始化列表或者赋值运算符来初始化,而std::vector只能通过构造函数来初始化。 4. 访问元素方式不同 std::array可以使用下标运算符或者迭代器来访问元素,而std::vector除了下标运算符和迭代器之外,还可以使用at()函数进行访问,该函数会检查访问的下标是否越界。 5. 速度不同 由于std::array的内存分配在栈上,访问元素时无需额外的内存访问开销,因此速度比std::vector更快。但是由于std::vector可以动态扩展,因此在大量数据的情况下,std::vector可能更快,因为std::array需要复制整个数组来进行扩展。 综上所述,std::array适用于大小固定的数组,且需要高效的内存管理和访问;而std::vector适用于大小不确定的数组,且需要动态扩展的情况。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fighting Horse

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值