You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

遍历vector容器时向其push元素报错的内部原因

遍历vector容器时向其push元素报错的内部原因

老哥,你碰到的这个问题,核心根源是在遍历vector的同时修改它的容量,导致迭代器失效,咱们掰开揉碎了说清楚:

首先先把你的代码贴出来方便对照:

class Solution {
public:
    void func(vector<int>& nums, vector<vector<int>>& ans, int target){
        if(target == -1){
            vector<int> v;
            ans.push_back(v);
            return;
        }
        func(nums, ans, target - 1);
        for(auto x : ans){
            x.push_back(nums[target]);
            ans.push_back(x);
        }
    }
    vector<vector<int>> subsets(vector<int>& nums) {
        vector<vector<int>> ans;
        func(nums, ans, nums.size() - 1);
        return ans;
    }
};

问题出在哪?

你用for(auto x : ans)这种范围for循环遍历ans的时候,底层其实是依赖vector的迭代器来逐个访问元素的。而vector的底层实现是连续的内存数组,它有个固定的“容量”(可以理解为当前分配的内存能装多少元素)。当你调用ans.push_back(x)的时候,如果当前元素个数已经等于容量,vector就会触发扩容操作:

  1. 重新申请一块更大的连续内存空间(通常是原来的2倍)
  2. 把旧内存里的所有元素拷贝/移动到新内存
  3. 释放旧的内存空间

这时候麻烦就来了:原来用来遍历的迭代器,指向的是已经被释放的旧内存地址,变成了“野指针”。后续循环再用这个失效的迭代器去访问元素,就会触发未定义行为——可能直接报错,也可能程序崩溃,完全看运气。

而且还有个额外的问题:你在遍历的同时往容器里加元素,会导致循环次数远超预期,因为每次push都会让容器的size变大,循环会一直遍历新加入的元素,直到触发扩容崩溃。

怎么修复?

最简单的办法是先记录遍历前容器的元素个数,只遍历到这个固定的个数,用索引访问而不是依赖迭代器,这样就不会受后续push操作的影响:

void func(vector<int>& nums, vector<vector<int>>& ans, int target){
    if(target == -1){
        vector<int> v;
        ans.push_back(v);
        return;
    }
    func(nums, ans, target - 1);
    // 先记录当前ans的元素个数,只遍历这些旧元素
    int old_size = ans.size();
    for(int i = 0; i < old_size; i++){
        vector<int> x = ans[i];
        x.push_back(nums[target]);
        ans.push_back(x);
    }
}

这样遍历的是扩容前的所有元素,不会碰到新加入的元素,也不会触发迭代器失效的问题,就能正常生成所有子集了。

备注:内容来源于stack exchange,提问作者ae80

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.16 09:55:32