按指针列出的 C++ 对象列表

c++ object list by pointer

本文关键字:C++ 对象 列表 指针      更新时间:2023-10-16

我想创建一个对象列表,只需保存指向每个对象中下一个对象的指针。

#include <iostream>
class A
{
    int v;
    A *next;
public:
    A(int temp):v(temp) {}
    A* createNext()
    {
        A temp(v+1);
        next = &temp;
        return next;
    }
    int getv(){return v;}
};
int main()
{
    A first(0);
    A * next = first.createNext();
    std::cout << next->getv() << "n";
    next = next->createNext();
    std::cout << next->getv() << "n";
}

当我执行这个程序时,它始终为我的第一个 cout 提供 1,但第二个是整数范围之外的随机数。

createNext() 函数中,您将在堆栈内存中创建一个对象,然后为其分配引用。但是,一旦该函数退出,堆栈帧将被清除,下一个指针将引用垃圾值。

A* createNext()
{
    A temp(v+1); // this creates an object on the stack
    next = &temp;
    return next;
}

相反,您需要在堆上创建对象,并将其返回。堆内存不绑定到函数,可以在分配堆内存的作用域之外进行访问。

A* createNext()
{
    next = new A(v+1); // this creates an object on the heap
    return next;
}

但是,如果在堆上分配对象(即使用 new (,则需要在之后解除分配它们(即使用 delete (。如果不这样做,就会产生所谓的"内存泄漏"。

使用更现代的C++功能,您可以减少内存管理的一些陷阱。尽管考虑到您问题的性质,但在使用这些抽象之前,您应该努力对C++中的内存分配有一个扎实的理解。

    A temp(v+1);
    next = &temp;
    return next;

你创建一个"局部"变量,即一个具有自动存储持续时间的变量,其生命周期在函数结束时结束,然后返回其地址。因此,您将返回超出范围的对象的地址,这是未定义的行为。

如果不检查你的逻辑,而只是专注于解决这个内存问题,你可能不得不写

    A* temp = new A(v+1);
    next = temp;
    return next;
   A* createNext()
    {
        A temp(v+1);
        next = &temp;
        return next;
    }

您返回指向本地对象的指针temp,这将超出范围,指针将悬空。从那时起,您所有的取消引用都是未定义的行为。考虑将std::unique_ptr与共享结合使用。或者只是使用std::forward_list提供的标准。