在删除动态分配对象的指针向量中的元素之前,我需要做什么?

时间:2010-10-31 01:21:28

标签: c++ pointers memory-management memory-leaks vector

我有一个向量,我用指向对象的指针填充。我正在努力学习良好的记忆管理,并提出一些一般性问题:

  1. 当我完成向量时,我必须遍历它并在每个指针上调用delete吗?
  2. 为什么我不必在没有新语句的情况下对向量或我声明的任何其他变量调用delete,但必须在指针上调用delete?
  3. 如果向量在返回的函数中声明(导致向量超出范围),C ++是否会为我释放指针的内存?

5 个答案:

答案 0 :(得分:23)

  1. 使用模板内存分配器实现向量,这些分配器为您处理内存管理,因此它们有点特殊。但作为一般经验法则,您不必对未使用delete关键字声明的变量调用new,因为堆栈和堆分配之间存在差异。如果在堆上分配了东西,则必须删除它(释放)以防止内存泄漏。
  2. 否。在迭代所有元素时,您必须明确地调用delete myVec[index]
  3. 例如:

    for(int i = 0; i < myVec.size(); ++i)
       delete myVec[i];
    

    话虽如此,如果您计划在向量中存储指针,我强烈建议使用boost::ptr_vector自动处理删除。

答案 1 :(得分:11)

  

当我完成向量时,我必须遍历它并在每个指针上调用delete吗?

嗯,您不必手动循环,也可以使用算法:

#include <vector>
#include <algorithm>
#include <memory>

int main()
{
    std::vector<Base*> vec;
    vec.push_back(new Derived());
    vec.push_back(new Derived());
    vec.push_back(new Derived());

    // ...

    std::for_each(vec.begin(), vec.end(), std::default_delete<Base>());
}

如果您没有C ++ 0x编译器,可以使用boost:

#include <boost/lambda/lambda.hpp>
#include <boost/lambda/construct.hpp>

std::for_each(vec.begin(), vec.end(), boost::lambda::delete_ptr());

或者您可以编写自己的仿函数:

struct delete_ptr
{
    template <class T>
    void operator()(T* p)
    {
        delete p;
    }
};

std::for_each(vec.begin(), vec.end(), delete_ptr());

答案 2 :(得分:3)

如果您有权访问C ++ 0x,也可以使用std :: unique_ptr。它取代了不能在容器中使用的已弃用的std :: auto_ptr。

答案 3 :(得分:3)

您使用new分配的所有内容以后都必须delete。您未使用new明确分配的对象不应该delete

如果您不想手动管理对象但希望向量“拥有”它们,那么最好按值存储对象而不是存储指针。因此,您可以使用std::vector<SomeClass*>代替std::vector<SomeClass>

答案 4 :(得分:2)

作为David Titarenco提到的boost::ptr_vector的替代方法,您可以轻松修改std :: vector以自动释放内存以包含删除指针:

template<class T>
class Group : public std::vector<T>
{
public:
    virtual ~Group() {};
};

template<class T>
class Group<T *> : public std::vector<T *>
{
public:
    virtual ~Group()
    {
        std::vector<T *>::reverse_iterator it;
        for (it = this->rbegin(); it != this->rend(); ++it)
            delete *it;
    }
};

std :: vector提供的所有功能都是继承的,因此您可以使用相同的方式添加项目:

Group<Foo *> *bar = new Group<Foo *>();
bar->push_back(new Foo());
bar->push_back(new DerivedFoo());

// Deleting the Group will free all memory allocated by contained pointers
delete bar;