标准列表,矢量,地图等占用的可用内存

时间:2011-01-17 14:09:45

标签: c++ memory-management stl

来自C#背景,我对C ++的内存管理只有最模糊的想法 - 我所知道的是我必须手动释放内存。因此,我的C ++代码编写方式使std::vectorstd::liststd::map类型的对象可以自由实例化,使用,但不会被释放。

直到我几乎完成了我的程序,我才意识到这一点,现在我的代码由以下几种模式组成:

struct Point_2
{
    double x;
    double y;
};

struct Point_3
{
    double x;
    double y;
    double z;
};

list<list<Point_2>> Computation::ComputationJob
    (list<Point_3>pts3D, vector<Point_2>vectors)
{
    map<Point_2, double> pt2DMap=ConstructPointMap(pts3D);
    vector<Point_2> vectorList = ConstructVectors(vectors);
    list<list<Point_2>> faceList2D=ConstructPoints(vectorList , pt2DMap);
    return faceList2D;
}

我的问题是,我必须释放列表用法的 every.single.one (在上面的示例中,这意味着我必须释放{{1 },pt2DMapvectorList)?那将是非常乏味的!我也可以重写我的faceList2D类,以便它不易发生内存泄漏。

知道如何解决这个问题吗?

3 个答案:

答案 0 :(得分:11)

否:如果对象未分配new,则无需明确释放/删除它们。当它们超出范围时,它们会自动解除分配。当发生这种情况时,会调用析构函数,它应该释放它们引用的所有对象。 (这称为Resource Acquisition Is Initialization, or RAIIstd::liststd::vector等标准类遵循此模式。)

如果您使用new,则应使用智能指针(scoped_ptr)或明确调用delete。调用delete的最佳位置是析构函数(出于异常安全的原因),尽管应尽可能使用智能指针。

答案 1 :(得分:2)

我能说的一般是C ++标准容器在场景下复制你的对象。你无法控制它。这意味着如果构造对象(在您的情况下为Point_2)涉及任何资源分配(例如:newmalloc调用),那么您必须编写自定义版本的复制构造函数和析构函数,使得当地图决定复制Point_2时,这会使其表现得非常明显。通常这涉及引用计数等技术。

许多人发现将复杂对象的指针放入标准容器而不是对象本身更容易。

如果你没有为你的对象做任何特殊的构造函数或析构函数(现在看来就是这种情况),那就没有任何问题了。一些容器(如地图)将在场景下进行动态分配,但这对您来说实际上是不可见的。 容器担心资源分配。你只需要担心你的。

答案 2 :(得分:0)

所有stl容器都会自动清理其内容,您必须关注的是清理动态分配的数据(即规则是:处理指针)。

例如,如果您有list<MyType> - 列表中包含某些自定义类型的对象 - 在销毁时它将调用~MyType(),它应该正确清理对象内容(即如果MyType有一些指向内部分配内存的指针,你应该在析构函数中删除它们。)

另一方面,如果你开始使用list<MyType*> - 容器现在如何正确地清理它,它包含一些标量值(就像整数一样)并且只删除指针本身,而不清除尖头内容,所以你需要手动清理它。

一个非常好的建议(很多年前曾帮助过我:))当从Java / C#切换到C ++时,要仔细跟踪每个动态内存对象的生命周期:a)创建它的地方,b)它被使用的地方,c )它何时何地被删除。 确保它只被清理一次,之后不会被引用!