在C++中动态分配列表

can*_*rem 0 c++ pointers list dynamic-memory-allocation dangling-pointer

我制作了一个可爱的通用(即模板)List类来处理C++中的列表.原因是我发现这个std::list类在日常使用中非常难看,而且由于我经常使用列表,我需要一个新的.主要的改进是,我的班级,我可以用来[]从中获取物品.此外,还有待实现的是一个IComparer对事物进行排序的系统.

我正在使用这个ListOBJLoader,我的类加载Wavefront .obj文件并将它们转换为网格.OBJLoader包含指向以下"类型"的指针列表:3D位置,3D法线,uv纹理坐标,顶点,面和网格.顶点列表具有必须链接到所有3D位置,3D法线和uv纹理坐标列表中的某些对象的对象.面链接到顶点,网格链接到面.所以他们都是相互联系的.

为简单起见,让我们考虑一下,在某些情况下,只有两个指针列表:List<Person*>List<Place*>.Personclass包含,其中包括字段List<Place*> placesVisitedPlace类包含字段List<Person*> peopleThatVisited.所以我们有结构:

class Person
{
    ...
  public:
    Place* placeVisited;
    ...
};

class Place
{
    ...
  public:
    List<People*> peopleThatVisited;
};
Run Code Online (Sandbox Code Playgroud)

现在我们有以下代码:

Person* psn1 = new Person();
Person* psn2 = new Person();

Place* plc1 = new Place();
Place* plc2 = new Place();
Place* plc2 = new Place();


// make some links between them here:
psn1->placesVisited.Add(plc1, plc2);
psn2->placesVisited.Add(plc2, plc3);

// add the links to the places as well
plc1->peopleThatVisited.Add(psn1);
plc2->peopleThatVisited.Add(psn1, psn2);
plc3->peopleThatVisited.Add(plc3);

// to make things worse:

List<Person*> allThePeopleAvailable;

allThePeopleAvailable.Add(psn1);
allThePeopleAvailable.Add(psn2);

List<Place*> allThePlacesAvailable;

allThePlacesAvailable.Add(plc1);
allThePlacesAvailable.Add(plc2);
allThePlacesAvailable.Add(plc3);
Run Code Online (Sandbox Code Playgroud)

全部完成.当我们到达时会发生什么}?所有的dtors都被调用,程序崩溃,因为它试图删除两次或更多次的东西.

我列表的dtor看起来像这样:

~List(void)
{
    cursor = begin;
    cursorPos = 0;

    while(cursorPos &#60; capacity - 1)
    {
        cursor = cursor->next;
        cursorPos++;
        delete cursor->prev;
    }

    delete cursor;
}
Run Code Online (Sandbox Code Playgroud)

在哪里Elem:

struct Elem
{
  public:
    Elem* prev;
    T value;
    Elem* next;
};
Run Code Online (Sandbox Code Playgroud)

并且T是通用List类型.

这让我们回到了这个问题:有什么方法可以安全地删除我的List课程?里面的元素可能是也可能不是指针,如果它们是指针,我希望能够,当我删除我的时候List,指定我是否要删除里面的元素或只是Elem它们周围的包装器.

聪明的指针可能是一个答案,但这意味着我不能拥有List<bubuType*>,但只是List<smart_pointer_to_bubuType>.这可能是好的,但又说:声明List<bubuType*>会导致没有错误或警告,并在某些情况下,智能指针会导致在执行一些问题:比如,我可能要宣布List<PSTR>一些WinAPI的回报.我认为将PSTR智能指针纳入其中将是一项艰巨的工作.因此,我认为我正在寻找的解决方案应该以某种方式与List模板的释放系统相关.

有任何想法吗?

sbi*_*sbi 11

甚至没有查看你的代码,我说:废弃它!

C++有一个列表类模板,它的效率和它一样,所有C++程序员都知道,并且编译器没有错误.

学习使用STL.1来自其他OO语言,STL可能看起来很奇怪,但是它的陌生性是一个潜在的原因,一种结合了抽象和表现的外星美- 在Stepanov出现并想到STL之前被认为是不可能的.
请放心,您并不是唯一一个努力理解STL的人.当它出现在我们身上时,我们都在努力去理解它的概念,了解它的特殊性,理解它是如何发展的.STL一个奇怪的野兽,但它设法将每个人认为永远无法组合的两个目标结合在一起,所以一开始就让它变得陌生.

我敢打赌编写自己的链表类曾经是C++程序员第二大最受欢迎的室内运动 - 就在编写自己的字符串类之后.我们这些谁已编程的C++ 15年前,如今享受剥开那些充满错误的,低效的,奇怪的,和未知的字符串,列表和字典类的旧代码腐烂,并与东西是非常替换它高效,良好已知,无错误.开始自己的列表课程(除教育目的外)必须是最糟糕的异端之一.

如果您使用C++编程,请尽快使用其框中最强大的工具之一.

1 请注意,术语"STL"命名源自Stepanov库的C++标准库的一部分(加上像std::string事后补充的STL接口之类的东西),而不是整个标准库.

  • 〜+ 1(〜意思是我不会投票:P),虽然我同意这里陈述的所有内容,但我认为这实际上并不是与处理对象生命周期的问题有关,而不是实现他的选择.自己的容器.如果他使用`std :: list <type*>`(或`std :: vector <type*>`)会出现同样的问题 (3认同)
  • @David:正如我所说,我甚至没有密切关注这个问题.关于C++中对象生命周期管理的问题很多,如果确实缺少这个问题,如果被问到`std :: list <type*>`,它会得到快速而有针对性的回答.但是编写自己的列表类(不是用于教育,而是因为你不同意std lib)只保证一个答案:不要. (3认同)