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

如何删除stl容器?

  •  5
  • yesraaj  · 技术社区  · 16 年前

    像stl中的vector这样的容器对象是如何被销毁的,即使它们是在堆中创建的?

    编辑

    如果容器持有指针,那么如何销毁这些指针对象

    12 回复  |  直到 16 年前
        1
  •  20
  •   Alex B    15 年前

    指针的STL容器不会清除指向的数据。它只会清理容纳指针的空间。如果希望向量清理指针数据,则需要使用某种智能指针实现:

    {
        std::vector<SomeClass*> v1;
        v1.push_back(new SomeClass());
    
        std::vector<boost::shared_ptr<SomeClass> > v2;
        boost::shared_ptr<SomeClass> obj(new SomeClass);
        v2.push_back(obj);
    }
    

    当作用域结束时,两个向量将释放其内部数组。v1将泄漏创建的SomeClass,因为数组中只有指向它的指针。v2不会泄漏任何数据。

        2
  •  5
  •   derobert    16 年前

    如果你有 vector<T*> ,您的代码需要在删除向量之前删除这些指针:否则,内存就会泄漏。

    知道C++不做垃圾收集,这是为什么(语法错误的错误,我写C++以来有一段时间)的例子:

    typedef vector<T*> vt;
    ⋮
    vt *vt1 = new vt, *vt2 = new vt;
    T* t = new T;
    vt1.push_back(t);
    vt2.push_back(t);
    ⋮
    delete vt1;
    

    最后一行( delete vt1; vt2

    (如果你想要一个在destroy上删除指针的向量类型,当然可以编写这样的类型。可能已经编写过。但是要小心删除其他人仍持有其副本的指针。)

        3
  •  3
  •   Mehrdad Afshari    16 年前

    当向量超出范围时,编译器会发出对其析构函数的调用,从而释放堆上分配的内存。

        4
  •  3
  •   JaredPar    16 年前

    1. 向量实例
    2. 实际的底层数组实现

    虽然是可配置的,但#2几乎总是存在于堆中#但是,1可以存在于堆栈或堆上,这取决于它的分配方式。例如

    void foo() { 
      vector<int> v;
      v.push_back(42);
    }
    

    那么#2是如何被摧毁的呢?当向量的第一部分被破坏时,它也会破坏第二部分。这是通过删除vector类的析构函数中的底层数组来完成的。

        5
  •  2
  •   Dominik Grabiec    16 年前

    如果将指针存储在STL容器类中,则需要在销毁对象之前手动删除它们。这可以通过在整个容器中循环并删除每个项来完成,或者通过使用某种智能指针类来完成。但是,不要使用auto_ptr,因为这根本不适用于容器。

    这样做的一个好的副作用是,您可以在程序中保留多个指针容器,但这些对象只属于其中一个容器,您只需要清理这一个容器。

    for (ContainerType::iterator it(container.begin()); it != container.end(); ++it)
    {
        delete (*it);
    }
    
        6
  •  2
  •   Michel    16 年前

    使用向量内部的智能指针,或者使用boost的ptr_向量。它将自动释放其中分配的对象。还有地图、布景等。

    http://www.boost.org/doc/libs/1_37_0/libs/ptr_container/doc/ptr_vector.html 主站点: http://www.boost.org/doc/libs/1_37_0/libs/ptr_container/doc/ptr_container.html

        7
  •  0
  •   zvrba    16 年前

        8
  •  0
  •   strager    16 年前

    要回答您的第一个问题:

    STL类没有什么特别之处(我希望如此)。它们的功能与其他模板类完全相同。因此,如果在堆上分配它们,它们不会自动销毁,因为C++没有垃圾收集(除非您用一些华丽的自动操作或某些东西告诉它)。如果将其分配到堆栈(没有新的),它很可能会被C++自动管理。

    对于第二个问题,这里有一个非常简单的ArrayOfTen类来演示C++中典型内存管理的基础知识:

    /* Holds ten Objects. */
    class ArrayOfTen {
        public:
            ArrayOfTen() {
                m_data = new Object[10];
            }
    
            ~ArrayOfTen() {
                delete[] m_data;
            }
    
            Object &operator[](int index) {
                /* TODO Range checking */
                return m_data[index];
            }
    
        private:
            Object *m_data;
    
            ArrayOfTen &operator=(const ArrayOfTen &) { }
    };
    
    ArrayOfTen myArray;
    myArray[0] = Object("hello world"); // bleh
    

    对于大多数(所有?)STL类型,调整大小是在幕后进行的,以确保有足够的内存集分配给您的元素。上面的类只支持十个对象的数组。它基本上是一个非常有限的对象类型[10]。

        9
  •  0
  •   xtofl Adam Rosenfield    16 年前

    template<typename T>
    struct Delete {
        void operator()( T* p ) const { delete p; }
    };
    
    std::vector< MyType > v;
    // ....
    std::for_each( v.begin(), v.end(), Delete<MyType>() );
    

    但是,当向量的内容要。。。嗯。。。共享。对

        11
  •  0
  •   Loki Astari    16 年前

    标准STL容器使用复制构造函数将原始对象的副本放置到容器中。当容器被销毁时,还会调用容器中每个对象的析构函数来安全地销毁该对象。


    问题是指针是POD数据。指针的复制构造函数只是复制地址,POD数据没有析构函数。如果希望容器管理指针,则需要:

    • 使用boost ptr容器。


    指针容器与STL容器相同,只是您将指针放入其中,但容器随后会获得指针指向的对象的所有权,并在容器销毁时解除对象的分配(通常通过调用delete)。

    int main()
    {
        boost::ptr_vector<int>    data;
    
        data.push_back(new int(5));
        data.push_back(new int(6));
    
        std::cout << data[0] << "\n";  // Prints 5.
        std::cout << data[1] << "\n";  // Prints 6.
    
    
    }   // data deallocated.
        // This will also de-allocate all pointers that it contains.
        // by calling delete on the pointers. Therefore this will not leak.
    

    还应该指出,容器中的智能指针是一种有效的替代方法,不幸的是std::auto_ptr<&燃气轮机;对于这种情况,不是有效的智能指针选择。

        12
  •  0
  •   Anton I. Sipos    15 年前

    STL容器与任何其他对象类似,如果您实例化一个,它将在堆栈上创建:

    std::vector<int> vec(10);
    

    与任何其他堆栈变量一样,它只存在于定义它的函数的范围内,不需要手动删除。STL容器的析构函数将调用容器中所有元素的析构函数。

    那么,您应该将什么内容放入容器中,而不是原始指针+1个jmucchiello用于启动boost::shared_ptr。在STL容器中使用boost::shared\u ptr是安全的(与std::auto\u ptr不同)。它使用一个简单的引用计数机制,可以安全地用于不包含循环的数据结构。