C++ vector调用insert插入元素结果不符合预期的原因解析
问题说明
需求:为std::vector中的每个原有元素,在其紧邻后方插入对应的相反数,要求不允许使用辅助vector或其他额外数据结构。
错误实现代码:
#include <iostream> #include <vector> int main() { std::vector < int > vek {1,2,3}; std::cout << vek[0] << " " << vek[1] << " " << vek[2] << std::endl; for (int i = 0; i < 3; i++) { std::cout << i << " " << vek[i] << std::endl; vek.insert(vek.begin() + i + 1, -vek[i]); } std::cout << std::endl; for (int i: vek) std::cout << i << " "; return 0; }
实际运行输出与预期不符:
1 2 3 0 1 // 预期应为0 1(因为vek[0]=1) 1 -1 // 预期应为1 2(因为vek[1]=2) 2 1 // 预期应为2 3(因为vek[2]=3) 1 -1 1 -1 2 3 // 预期应为1 -1 2 -2 3 -3
错误原因与实际运行逻辑
问题出在两个被忽略的特性和循环逻辑错误:
std::vector::insert的固有行为:向vector任意位置插入元素时,插入位置及之后的所有元素会整体向后顺移1位,vector总长度+1,元素下标会重新排列- 循环逻辑缺陷:原代码循环步长固定为+1、循环终止条件硬编码为
i<3,完全没有考虑插入操作带来的元素位置偏移
逐轮拆解循环的实际执行过程:
- 循环启动前,vek长度为3,下标对应元素:
0:1, 1:2, 2:3 - 第一轮i=0:取
vek[0]=1,在下标1的位置插入-1。插入后元素顺移,vek长度变为4,元素为0:1, 1:-1, 2:2, 3:3,这一步输出符合预期 - 第二轮i=1:此时下标1的位置已经是上一轮插入的-1,不是原有的2。代码取
vek[1]=-1,在下标2的位置插入-(-1)=1,插入后vek长度变为5,元素为0:1, 1:-1, 2:1, 3:2, 4:3,输出1 -1,和预期偏离 - 第三轮i=2:此时下标2的位置是上一轮插入的1,不是原有的3。代码取
vek[2]=1,在下标3的位置插入-1,插入后vek长度变为6,元素为0:1, 1:-1, 2:1, 3:-1, 4:2, 5:3,输出2 1,完全偏离预期 - 循环结束,最终遍历输出的结果就是
1 -1 1 -1 2 3,和实际运行结果一致。
修复方案
不需要引入额外数据结构,只需要调整循环逻辑:记录vector初始的元素个数作为循环总次数,每次插入完成后,通过偏移计算定位下一个待处理的原元素下标即可。
修复后的可运行代码:
#include <iostream> #include <vector> int main() { std::vector < int > vek {1,2,3}; // 记录初始元素个数,只需要处理原有元素 int original_len = vek.size(); for (int i = 0; i < original_len; i++) { // 每插入一个元素,后续原元素位置后移2位,用2*i定位当前待处理原元素的下标 vek.insert(vek.begin() + 2*i + 1, -vek[2*i]); } // 验证输出 for (int i: vek) std::cout << i << " "; // 输出1 -1 2 -2 3 -3,符合预期 return 0; }
内容的提问来源于stack exchange,提问作者Rocket Procd
相关产品推荐
相关产品推荐

