为何向空vector<int>输入整数时两段代码运行结果不同?
为什么第一段vector循环死循环,第二段却能正常运行?
这个问题的核心在于vector迭代器的有效性以及你在循环条件中如何使用begin()。咱们一步步拆解:
第一段代码失效的原因
先看你的第一段代码:
#include <iostream> #include <vector> int main(void) { std::vector<int> ivec; int n = 4; for (std::vector<int>::iterator iter = ivec.begin(); iter != ivec.begin() + n; ++iter) { int x; std::cin >> x; ivec.push_back(x); } return 0; }
这里有两个致命问题:
- 非法迭代器的创建:初始时
ivec是空的,ivec.begin()和ivec.end()指向同一个位置。此时ivec.begin() + 4是完全非法的——vector的大小只有0,你不能从起始迭代器偏移超过size()-1的位置,这属于越界访问,行为是未定义的。 - 迭代器失效+循环条件动态变化:每次执行
push_back(x)时,如果vector当前的容量不足以容纳新元素,它会重新分配一块更大的内存,把旧元素拷贝过去,这会导致所有指向原内存的迭代器全部失效——包括你循环里的iter。更糟的是,每次循环判断条件时,你都重新计算ivec.begin(),这个begin()是当前vector的新起始迭代器(可能已经因为扩容变了)。拿一个失效的迭代器和一个不断变化、甚至非法的迭代器比较,永远不会相等,循环自然会无限跑下去。
第二段代码“正常运行”的本质
再看调整后的第二段代码:
#include <iostream> #include <vector> int main(void) { std::vector<int> ivec; int n = 4; std::vector<int>::iterator tempiter = ivec.begin(); for (std::vector<int>::iterator iter = tempiter; iter != tempiter + n; ++iter) { int x; std::cin >> x; ivec.push_back(x); } std::cout << "**********************************" << std::endl; for (std::vector<int>::iterator iter = ivec.begin(); iter != ivec.end(); ++iter) std::cout << *iter << std::endl; return 0; }
你这里的操作其实是依赖编译器实现的巧合,严格来说依然存在未定义行为:
- 你把初始空vector的
begin()存在了tempiter里,之后循环条件里的tempiter + 4是基于这个初始迭代器计算的固定偏移。 - 在很多编译器中,vector的迭代器本质是指向数组的指针,
tempiter是初始空vector的起始地址(可能是一个空指针或者某个初始内存地址),tempiter +4就是这个地址往后跳4个int的位置。 - 循环里
iter从tempiter开始,每次++iter,不管vector怎么扩容、原迭代器失效,你只是在比较iter是否等于这个固定的地址偏移值,所以循环会恰好执行4次,之后退出。这就是你看到它“正常运行”的原因,但这不是标准C++保证的行为——换个编译器或者环境,可能就会崩溃或者出现奇怪的结果。
正确的写法
想要安全地控制循环次数,完全不需要用迭代器来判断,直接用计数器或者vector的size()就好:
方法1:用计数器控制循环(最直观)
#include <iostream> #include <vector> int main(void) { std::vector<int> ivec; const int n = 4; for (int i = 0; i < n; ++i) { int x; std::cin >> x; ivec.push_back(x); } std::cout << "**********************************" << std::endl; for (int num : ivec) { // 用范围for循环更简洁 std::cout << num << std::endl; } return 0; }
方法2:用vector的size判断
#include <iostream> #include <vector> int main(void) { std::vector<int> ivec; const int n = 4; while (ivec.size() < n) { int x; std::cin >> x; ivec.push_back(x); } std::cout << "**********************************" << std::endl; for (int num : ivec) { std::cout << num << std::endl; } return 0; }
这两种写法都是标准C++保证的安全行为,不会出现迭代器失效或者未定义行为的问题。
内容的提问来源于stack exchange,提问作者Sleeping On a Giant's Shoulder
相关产品推荐
相关产品推荐

