C++中vector的异常行为疑问:为何两种遍历方式结果不同?
[]和at()的核心区别 嘿,这个问题问得太到位了,刚好能帮你搞明白C++ vector里两个常用访问方式的本质,还有越界访问的底层坑~
先拆解你代码里的关键问题:
当你执行vec={2,3,4}后,这个vector的实际元素数量(size)是3,合法的索引范围是0、1、2——根本不存在索引为3的元素位置。
为什么第一个for循环用[]能输出9?
vector::operator[](也就是你用的vec[i])是不做边界检查的!它的底层逻辑很简单:
vector的元素存在连续内存块里,它会直接计算目标地址:起始地址 + i * sizeof(int),然后直接读写这块内存。
你写vec[3]=9的时候,其实是往vector已分配内存的末尾之外的一块内存里写了9——如果这块内存刚好属于你的程序(没触发系统的内存保护),那数据就存进去了。之后第一个for循环用[]读这块越界的内存,自然能输出9,但这是典型的未定义行为:今天能运行,换个编译器、操作系统甚至重启电脑,都可能直接崩溃、输出乱码,或者悄悄破坏其他变量的数据,绝对不能依赖这种行为!
为什么第二个for循环用at()就输出不了?
vector::at()和[]最大的区别就是它会做严格的边界检查!
每次调用at(i)的时候,它都会先判断i是否小于vector的size()。如果i >= size(),它会直接抛出std::out_of_range异常——如果你的代码没捕获这个异常,程序就会直接终止,自然输出不了那个越界的9。
为什么初始vector有4个元素就没问题?
如果初始vector有4个元素,那它的size()就是4,合法索引范围是0-3。不管用[]还是at(),访问索引3都是在合法范围内的,不会触发越界,所以两个循环都能正常输出。
给新手的小建议
写代码的时候,尤其是调试阶段,尽量用at()代替[]——它能帮你快速定位越界的问题,避免出现那种“有时候正常有时候崩溃”的诡异bug。如果一定要用[],记得先检查索引是否在0 <= i < vec.size()的范围内哦~
内容的提问来源于stack exchange,提问作者Shawon Eric

