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

C++ Partition类makeSet返回迭代器main中解引用抛异常修复

问题背景

实现了Partition分区合并结构,该结构支持创建集合并返回集合对应的位置标识,代码中Partition类内部嵌套了listSet类。

故障现象与疑问
  • 在makeSet()函数内部可以正常输出对应位置的元素
  • 当函数返回集合位置后,在main()函数中尝试输出该位置的元素时会抛出异常
  • 不确定makeSet()的返回值数据类型定义是否正确,咨询修复方案,以及是否需要将makeSet()的返回值改为指针类型
复现代码
#ifndef LISTSET_H
#define LISTSET_H

#include <iostream>
#include <vector>
using namespace std;

template<typename E>
class Partition
{
    public:
typedef typename vector<E>::iterator Itr; // 定义迭代器类型

public:
    template <typename E>
    class listSet // 嵌套listSet类
    {   
        private:
            vector<E> L;
            int size;

        public:
            listSet() { size = 1; }
            int getSize() { return size; }

            Itr insert(E e) /*返回元素位置*/
            { 
                L.push_back(e);
                Itr p = L.begin();
                //cout << *p << endl; // 此处打印正常
                return p;
            }
    };

    public:
      Itr makeSet(E e);
};

template<typename E>
 typename Partition<E>::Itr Partition<E>::makeSet(E e)
{
 listSet<E> set; 
 Itr p = set.insert(e);
 cout << *p << endl; // 此处打印正常

 return p;
}
#endif 

int main()
{
Partition<int> set1;
Partition<int>::Itr  p1, p2, p3;
p1 = set1.makeSet(1);
p2 = set1.makeSet(2);

cout << *p1 << endl; // 此处触发异常
}
报错参考

运行报错截图

故障根因

该异常是典型的悬空迭代器问题,和返回值是否改为指针无直接关联:

  • makeSet()中定义的listSet<E> set是栈上局部对象,函数执行完成返回时,该对象会被立刻析构,其内部存储元素的vector<E> L占用的内存会被系统回收
  • 返回的迭代器p指向这块已经被释放的内存:函数内部打印时局部对象尚未析构,因此可以正常输出;回到main函数时内存已失效,访问就会触发段错误/异常
  • 代码额外隐患:嵌套类listSet上重复定义的template <typename E>会遮蔽外层Partition类的模板参数E,存在类型匹配风险;同时Partition类没有持久化存储创建出的集合对象,完全无法实现分区合并的基础逻辑。
修复方案

不需要将返回值改为指针,核心是保证迭代器指向的内存生命周期长于迭代器的使用周期:

  1. 在Partition类中添加成员容器存储所有创建的listSet对象,保证这些对象的生命周期和Partition实例一致,不会随makeSet函数返回被销毁
  2. 移除嵌套类多余的模板声明,避免模板参数遮蔽问题
  3. 遵守vector迭代器使用规则,只要vector不发生扩容、析构,返回的迭代器就可以正常访问

修正后的核心代码示例:

template<typename E>
class Partition
{
public:
    typedef typename vector<E>::iterator Itr;
    // 移除嵌套类多余的template声明,避免参数遮蔽
    class listSet
    {   
    private:
        vector<E> L;
        int size;
    public:
        listSet() { size = 1; }
        int getSize() { return size; }
        Itr insert(E e)
        { 
            L.push_back(e);
            return L.begin();
        }
    };
private:
    // 持久化存储所有创建的集合,生命周期与Partition实例绑定
    vector<listSet> sets;
public:
    Itr makeSet(E e);
};

template<typename E>
typename Partition<E>::Itr Partition<E>::makeSet(E e)
{
    // 新集合存入成员容器,不会随函数返回销毁
    sets.emplace_back();
    Itr p = sets.back().insert(e);
    cout << *p << endl;
    return p;
}

内容的提问来源于stack exchange,提问作者Jun

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 02:48:29