LUCYprince 2025-02-11 13:18 采纳率: 50%
浏览 31
已结题

在写力扣遍历vector<vector<int>>的时候遇到了heap-use-after-free on address报错,不知道怎么改

在写力扣78遍历vector<vector>的时候遇到了heap-use-after-free on address报错。
当我的代码中用for auto遍历ans时,力扣会对此for循环报错:

vector<vector<int>> subsets(vector<int>& nums) {
        vector<vector<int>> ans;
        ans.push_back({});
        if(nums.size()){
        for(int x:nums)
        {
            int k=ans.size();
            **for(vector<int> vec:ans)**
            {
                //vector<int> vec=ans[j];
                vec.push_back(x);
                ans.push_back(vec);
            }
        }
        }
        return ans;
    }

img

但是当单独用for循环遍历ans的时候,就可以顺利通过。

vector<vector<int>> subsets(vector<int>& nums) {
        ans.push_back({});
        if(nums.size()){
        for(int x:nums)
        {
            int k=ans.size();
            for(int j=0;j<k;j++)
            {
                vector<int> vec=ans[j];
                vec.push_back(x);
                ans.push_back(vec);
            }
        }
        }
        return ans;
    }

我实在不明白这个原因是什么,向大家请教。

  • 写回答

4条回答 默认 最新

  • 道友老李 JWE233286一种基于机器视觉的水表指针读数识别及修正的方法 专利发明者 2025-02-11 13:18
    关注
    让【道友老李】来帮你解答,本回答参考gpt编写,并整理提供,如果还有疑问可以点击头像关注私信或评论。
    如果答案让您满意,请采纳、关注,非常感谢!
    在你的代码中遇到的“heap-use-after-free”错误,通常意味着你试图访问或操作已经被释放或者不再有效的内存。这种问题在C++中是较为常见的,尤其在使用动态内存管理(如`std::vector`)的时候。我们来一步步分析你的情况。

    问题分析

    你的代码涉及到对std::vector<std::vector<int>>的遍历和修改。下面是你代码中涉及的关键部分:

    第一种写法

    for (vector<int> vec : ans) {
        vec.push_back(x);
        ans.push_back(vec);
    }
    

    在这段代码中,当你使用范围for循环(for (vector<int> vec : ans))时,会复制ans中的每一个元素到vec中。这个复制过程会导致vecans保持独立的状态。后面对vec的修改不会影响ans中的原始元素。但是,因为你在循环中修改ans,并且没有额外的控制来避免在遍历时增加元素,这就会导致大小和结构的变化,且可能在重复访问时导致内存错误

    正确做法

    而在你给出的另外一段代码中,使用了索引的方式遍历:

    第二种写法

    for (int j = 0; j < k; j++) {
        vector<int> vec = ans[j];
        vec.push_back(x);
        ans.push_back(vec);
    }
    

    在这个版本中,由于你使用了一个基本的for循环,且通过索引访问ans,这使得在每一次循环中,你都清楚自己访问的是ans中有效的元素,并且不会像第一种写法那样在遍历过程中改变ans的结构和大小。

    解决方案

    建议在遍历并修改容器时,使用基于索引的循环,或在遍历时首先将原始数据保存在一个临时变量中。 示例代码

    #include <vector>
    std::vector<std::vector<int>> subsets(std::vector<int>& nums) {
        std::vector<std::vector<int>> ans;
        ans.push_back({});
        if (nums.size()) {
            for (int x : nums) {
                int k = ans.size();
                for (int j = 0; j < k; j++) { // 使用基于索引的遍历
                    std::vector<int> vec = ans[j]; // 复制,避免直接修改
                    vec.push_back(x);
                    ans.push_back(vec);
                }
            }
        }
        return ans;
    }
    

    总结

    对于动态修改的容器,建议使用基于索引的循环方式来避免遍历过程中结构的改变带来的问题。这不仅可以避免潜在的内存访问错误,还可以提高代码的易读性和稳定性。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

问题事件

  • 系统已结题 2月20日
  • 已采纳回答 2月12日
  • 创建了问题 2月11日