代码之家  ›  专栏  ›  技术社区  ›  a_familiar_wolf

c++指针对象列表[重复]

  •  1
  • a_familiar_wolf  · 技术社区  · 7 年前

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

    #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,但第二个cout是一个超出整数范围的随机数。

    3 回复  |  直到 7 年前
        1
  •  4
  •   Alan    7 年前

    在您的 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++中的内存分配有一个坚实的理解。

        2
  •  2
  •   Stephan Lechner    7 年前

    具有

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

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

    如果不太检查逻辑,只专注于解决这个内存问题,您可能需要编写

        A* temp = new A(v+1);
        next = temp;
        return next;
    
        3
  •  0
  •   Hatted Rooster    7 年前
       A* createNext()
        {
            A temp(v+1);
            next = &temp;
            return next;
        }
    

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